unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Unbalanced change hooks (part 2)
@ 2016-07-31 12:16 Alan Mackenzie
  2016-07-31 13:58 ` Noam Postavsky
                   ` (2 more replies)
  0 siblings, 3 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-07-31 12:16 UTC (permalink / raw)
  To: emacs-devel; +Cc: Óscar Fuentes, Richard Copley

Hello, Emacs.

There are several functions in .../src/insdel.c which have a parameter
`prepare'.  The meaning of `prepare' is "direct the function to call
prepare_to_modify_buffer" (YUCK!).  Thus, whether or not
before-change-functions is invoked is determined by the `prepare'
parameter.

The pertinent functions are insert_1_both, replace_range, del_range_1,
del_range_byte, and del_range_both.  These functions fall into two
groups, the first two in group 1 and the rest in group 2.  Those in group
2 always call signal_after_change, those in group 1 never do.

There are invocations of group 2 functions with `prepare' false.  This
wrongly invokes after-change-functions without having invoked
before-change-functions.

All the invocations of group 1 functions I've checked so far balance a
true `prepare' with an explicit call of signal_after_change.

At the heart of the problem is the lack of coherence in
prepare_to_modify_buffer.  This function has no definite coherent
function, the best description that can be given it being "perform some
of the things which need doing before a buffer change".  It is unclear
which of these things is unwanted when `prepare' is set to false.

The group 2 functions always invoke after-change-functions, so they must
always invoke before-change-functions.  In Finsert_file_contents there
are instances of del_range_byte with `prepare' false.  The spurious lack
of the before-change-functions invocation fouls up CC Mode, causing bug
#240[79]4.

I propose that the call to signal_before_change should be removed from
prepare_to_modify_buffer, and that it should be called explicitly from
the places it is needed.  This would allow bug #240[79]4 to be fixed.

Comments?

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 12:16 Unbalanced change hooks (part 2) Alan Mackenzie
@ 2016-07-31 13:58 ` Noam Postavsky
  2016-07-31 15:21   ` Alan Mackenzie
  2016-07-31 15:03 ` Eli Zaretskii
  2016-08-01 16:38 ` Richard Stallman
  2 siblings, 1 reply; 189+ messages in thread
From: Noam Postavsky @ 2016-07-31 13:58 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Óscar Fuentes, Richard Copley, Emacs developers

On Sun, Jul 31, 2016 at 8:16 AM, Alan Mackenzie <acm@muc.de> wrote:
>
> The pertinent functions are insert_1_both, replace_range, del_range_1,
> del_range_byte, and del_range_both.  These functions fall into two
> groups, the first two in group 1 and the rest in group 2.  Those in group
> 2 always call signal_after_change, those in group 1 never do.

replace_range should be in group 2 as well, no?

>
> There are invocations of group 2 functions with `prepare' false.  This
> wrongly invokes after-change-functions without having invoked
> before-change-functions.

replace_range has one call with prepare = false, it's in
Fsubst_char_in_region. I think the idea is that the caller takes care
of calling both before (by calling modify_text) and after (by explicit
call and/or(??) by replace_range) change functions, though the code is
sufficiently convuluted that I can't really say whether it works
correctly or not.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 12:16 Unbalanced change hooks (part 2) Alan Mackenzie
  2016-07-31 13:58 ` Noam Postavsky
@ 2016-07-31 15:03 ` Eli Zaretskii
  2016-07-31 17:28   ` Alan Mackenzie
                     ` (2 more replies)
  2016-08-01 16:38 ` Richard Stallman
  2 siblings, 3 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-07-31 15:03 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Sun, 31 Jul 2016 12:16:42 +0000
> From: Alan Mackenzie <acm@muc.de>
> Cc: Óscar Fuentes <ofv@wanadoo.es>,
> 	Richard Copley <rcopley@gmail.com>
> 
> I propose that the call to signal_before_change should be removed from
> prepare_to_modify_buffer, and that it should be called explicitly from
> the places it is needed.  This would allow bug #240[79]4 to be fixed.
> 
> Comments?

Some.

First, I don't agree with your conclusion that calls to
before-change-functions and after-change-functions must always be
balanced.  For starters, they aren't, and never have been.  Neither is
it written anywhere that they should, and your interpretation of the
ELisp manual seems to take the desired world for the real one.

My interpretation of these two variables is that they are two hooks
provided for different kinds of features, because hooking into both
should not generally be required.  It should suffice for an
application that wants to react to a change in a buffer to hook into
after-change-functions only.

But even if I agree, for the sake of argument, with your
interpretation, let's put this issue into a proper perspective, okay?
We have a single major mode (albeit a very important one, one that I
use every day) that under very specific conditions apparently fails to
discard its caches, because its design assumed calls to these two
hooks will always be balanced.  As a solution, you are proposing a
change in a very low-level and delicate part of Emacs, which means
significant changes to code that was basically unchanged for more than
20, if not 30 years.  This code is involved in almost every operation
on buffer text, and so changes you propose will necessarily cause
ripples all over Emacs.  Just look what the code you propose to change
does:

  . call barf-if-buffer-read-only
  . set the buffer's redisplay flag
  . affect the undo recording
  . save the region when select-active-regions is non-nil
  . sets deactivate-mark non-nil

Can you imagine how much Lisp code and basic features will be affected
by calling this where we never did before?  All that for the benefit
of a single major mode that fails in a single, albeit important use
case?

I'm sorry, but that makes very little sense to me.

So I suggest to take one or two steps back, and try to find a safer
solution for the problem.  Doing so will also greatly enhance the
chances of Emacs users to see the solution in the next Emacs release
(whereas doing what you suggest will push it back to Emacs 26 or maybe
even later).

Questions:

1) Why does CC Mode need both hooks?  What does it do in each one of
them, in the specific use case reported in the named bugs?  And why
isn't it enough to make only the change you proposed in part 1 of your
report?

2) Can this problem be fixed in CC Mode itself, without touching
either insert-file-contents or insdel.c functions?

3) If the answer to 2) above is a categorical NO (but please provide
enough arguments so we could be very sure it is that), then I _might_
be convinced to consider changes to insert-file-contents only, and
only for the case when both VISIT and REPLACE are non-nil.  That's
because I think this combination is only used by revert-buffer and
similar functionality (if someone knows about other callers that do
this, please holler), so the ripples will be not as wide as if we mess
with insdel.c.  (Still, even this possibility scares the living s**t
out of me; it should do that to you as well.)  To this end, please
tell which calls to del_range_byte in insert-file-contents are
involved with this use case and cause trouble to CC Mode, and maybe we
could change only those, in addition to the 'if' clause that guards
the call to before-change-functions.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 13:58 ` Noam Postavsky
@ 2016-07-31 15:21   ` Alan Mackenzie
  0 siblings, 0 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-07-31 15:21 UTC (permalink / raw)
  To: Noam Postavsky; +Cc: Óscar Fuentes, Richard Copley, Emacs developers

Hello, Noam.

On Sun, Jul 31, 2016 at 09:58:50AM -0400, Noam Postavsky wrote:
> On Sun, Jul 31, 2016 at 8:16 AM, Alan Mackenzie <acm@muc.de> wrote:

> > The pertinent functions are insert_1_both, replace_range, del_range_1,
> > del_range_byte, and del_range_both.  These functions fall into two
> > groups, the first two in group 1 and the rest in group 2.  Those in group
> > 2 always call signal_after_change, those in group 1 never do.

> replace_range should be in group 2 as well, no?

Er, yes, it should.  ;-)  So we have a group of 4 and a single function.
Thanks for spotting that.

> > There are invocations of group 2 functions with `prepare' false.  This
> > wrongly invokes after-change-functions without having invoked
> > before-change-functions.

> replace_range has one call with prepare = false, it's in
> Fsubst_char_in_region. I think the idea is that the caller takes care
> of calling both before (by calling modify_text) and after (by explicit
> call and/or(??) by replace_range) change functions, though the code is
> sufficiently convoluted that I can't really say whether it works
> correctly or not.

By taking signal_after_change out of prepare_to_modify_buffer, I'm
rather hoping to reduce the convolution.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 15:03 ` Eli Zaretskii
@ 2016-07-31 17:28   ` Alan Mackenzie
  2016-07-31 18:11     ` Eli Zaretskii
                       ` (2 more replies)
  2016-08-09 15:01   ` Alan Mackenzie
  2016-08-19 14:51   ` Phillip Lord
  2 siblings, 3 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-07-31 17:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, emacs-devel

Hello, Eli.

On Sun, Jul 31, 2016 at 06:03:19PM +0300, Eli Zaretskii wrote:
> > Date: Sun, 31 Jul 2016 12:16:42 +0000
> > From: Alan Mackenzie <acm@muc.de>
> > Cc: Óscar Fuentes <ofv@wanadoo.es>,
> > 	Richard Copley <rcopley@gmail.com>

> > I propose that the call to signal_before_change should be removed from
> > prepare_to_modify_buffer, and that it should be called explicitly from
> > the places it is needed.  This would allow bug #240[79]4 to be fixed.
 
> > Comments?

> Some.

> First, I don't agree with your conclusion that calls to
> before-change-functions and after-change-functions must always be
> balanced.  For starters, they aren't, and never have been.  Neither is
> it written anywhere that they should, and your interpretation of the
> ELisp manual seems to take the desired world for the real one.

The pertinent section of Elisp ("Change Hooks") says:

    These hook variables let you arrange to take notice of ALL changes
    in ALL buffers.  [My emphasis]

Your interpretation of that seems to be that each buffer change will
call _at least_ one of before-... and after-..., but not necessarily
both.  That doesn't seem sensible to me.

Further down, in `before_change_functions' (and we have the same thing
in `after_change_functions') we have:

    This variable holds a list of functions to call before any buffer
    modification.

I can't see any sensible interpretation of "any ... modification" other
than "each and every modification".  I've been relying on this for many
years.

Looked at another way, how can it be sensible to call just one of these
hooks?  Like, if you were redesigning Emacs from scratch, are there any
categories of buffer modifications in which you would call only
after-change-functions, and not before-c-f?

> My interpretation of these two variables is that they are two hooks
> provided for different kinds of features, because hooking into both
> should not generally be required.  It should suffice for an
> application that wants to react to a change in a buffer to hook into
> after-change-functions only.

No.  A program (such as CC Mode) reacts to a _change_, not merely to
what a buffer looks like after a change.  A buffer change loses
information, so in the general case, any required info needs to be
recorded by before-change-functions before it gets lost in the change,
so that it can be used by after-change-functions.

As a concrete example of this, suppose we have this in a buffer:

    #define foo() first line \
                  second line \
	          third line \
	          fourth line

, and the change consists of deleting the backslash on L2.
before-change-functions will have noted that all four lines are in the
"active area".  after-change-functions unassisted would merely see that
the "active area" consists of L1 and L2.  The info from before-change
enables after-change to operate on the entire four lines.

> But even if I agree, for the sake of argument, with your
> interpretation, let's put this issue into a proper perspective, okay?
> We have a single major mode (albeit a very important one, one that I
> use every day) that under very specific conditions apparently fails to
> discard its caches, ....

Being precise, two critical variables were dirty store from the previous
invocation of c-after-change, not having been set in the missing call to
before-change-functions.

> .... because its design assumed calls to these two hooks will always
> be balanced.  As a solution, you are proposing a change in a very
> low-level and delicate part of Emacs, which means significant changes
> to code that was basically unchanged for more than 20, if not 30
> years.

prepare_to_modify buffer has been modified lots of times in recent
years.  (I count six modifications since 2014-01.)

> This code is involved in almost every operation on buffer
> text, and so changes you propose will necessarily cause ripples all
> over Emacs.  Just look what the code you propose to change does:

>   . call barf-if-buffer-read-only
>   . set the buffer's redisplay flag
>   . affect the undo recording
>   . save the region when select-active-regions is non-nil
>   . sets deactivate-mark non-nil

I'm not proposing to change any of that at all.  What I'm proposing is
strictly limited, and could be accompished in two steps, as follows:

1. (Pure refactoring).  Remove the call to signal_before_change from
prepare_to_modify_buffer.  Insert an explicit call to s_b_c after each
invocation of p_t_m_b.  Restore the check on inhibit_modification_hooks
in s_b_c.

2. Where a call to signal_buffer_change is within an "if (prepare) ..."
construct, move it to after that construct, so that

    if (prepare)
      {
        prepare_to_modify_buffer (...);
	signal_after_change (...);
      }

would become

    if (prepare)
      prepare_to_modify_buffer (...);
    signal_after_change (...);

.

> Can you imagine how much Lisp code and basic features will be affected
> by calling this where we never did before?  All that for the benefit
> of a single major mode that fails in a single, albeit important use
> case?

> I'm sorry, but that makes very little sense to me.

Please reconsider carefully the concrete proposal I've made (above) and
judge whether it will really affect very much at all.  I can foresee
that nothing will happen except the desired invocations of
before-change-functions being made.

I'm not entirely sure that only CC Mode will be helped here.  The value
of before-change-functions in many major modes contains the function
syntax-ppss-flush-cache.  There is a good chance that some call of, say,
del_range_byte is going to leave the syntax-ppss cache stale and
invalid, a difficult situation to diagnose.

> So I suggest to take one or two steps back, and try to find a safer
> solution for the problem.  Doing so will also greatly enhance the
> chances of Emacs users to see the solution in the next Emacs release
> (whereas doing what you suggest will push it back to Emacs 26 or maybe
> even later).

> Questions:

> 1) Why does CC Mode need both hooks?

I think I've already answered this above.

> What does it do in each one of them, in the specific use case reported
> in the named bugs?

It should calculate the two variables c-new-BEG and c-new-END (which
bound the active region) in c-before-change, and these get modified in
c-after-change.  In the bug situation, these variables simply held stale
values from the previous c-after-change call (which was from
transpose-lines).  Specifically, c-after-change modified c-new-END by
subtracting old-len.  This happened to make c-new-END < c-new-BEG.  So a
subsequent re-search-forward invocation had the limit on the wrong side
of point and threw an error.

> And why isn't it enough to make only the change you proposed in part 1
> of your report?

I tried that, but it didn't work.  With the help of gdb, it was clear
that the missing before-change-functions came from an invocation of
del_range_byte with `prepare' false, rather than directly from
Finsert_file_contents.

> 2) Can this problem be fixed in CC Mode itself, without touching
> either insert-file-contents or insdel.c functions?

I honestly don't know.  That would require extensive redesign if it's
possible.  That would need something like creating a new cache to
hold the information for the entire buffer which is currently determined
in c-before-change.  A simple workaround would be to ignore (i.e. not
process) an out of sequence invocation of c-after-change, but that's
hardly ideal.  I suspect I'm going to have to do that anyway in
standalone CC Mode.

> 3) If the answer to 2) above is a categorical NO (but please provide
> enough arguments so we could be very sure it is that), then I _might_
> be convinced to consider changes to insert-file-contents only, and
> only for the case when both VISIT and REPLACE are non-nil.  That's
> because I think this combination is only used by revert-buffer and
> similar functionality (if someone knows about other callers that do
> this, please holler), ....

The actual operation was C-x C-f where the file was already visited in
Emacs, but had been modified outside of Emacs, so Finsert_file_contents
went through the code which attempts to preserve markers, etc.

> .... so the ripples will be not as wide as if we mess with insdel.c.
> (Still, even this possibility scares the living s**t out of me; it
> should do that to you as well.)  To this end, please tell which calls
> to del_range_byte in insert-file-contents are involved with this use
> case and cause trouble to CC Mode, and maybe we could change only
> those, in addition to the 'if' clause that guards the call to
> before-change-functions.

The del_range_byte call which I caught with gdb last night was, I think,
the one at fileio.c L4037.  I don't know the code well enough to say
that that's the only one which might trigger.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 17:28   ` Alan Mackenzie
@ 2016-07-31 18:11     ` Eli Zaretskii
  2016-07-31 18:52       ` Eli Zaretskii
                         ` (2 more replies)
  2016-07-31 18:55     ` Stefan Monnier
  2016-07-31 19:21     ` Eli Zaretskii
  2 siblings, 3 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-07-31 18:11 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Sun, 31 Jul 2016 17:28:04 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
>     This variable holds a list of functions to call before any buffer
>     modification.
> 
> I can't see any sensible interpretation of "any ... modification" other
> than "each and every modification".  I've been relying on this for many
> years.

You are forgetting that "buffer modifications" is not rigorously
defined in Emacs.  Let me remind you that in so many places we pretend
that no changes were made to a buffer, while in fact there were.

Given this fact, "any modification" has no meaning, beyond the
tautological "modifications that Emacs developers decided to treat as
such".

IOW, what the code does, and has been doing for many moons, is in this
case a de-facto _definition_ of what should be done.

> Looked at another way, how can it be sensible to call just one of these
> hooks?

I gave one such interpretation.

> Like, if you were redesigning Emacs from scratch, are there any
> categories of buffer modifications in which you would call only
> after-change-functions, and not before-c-f?

But we are not redesigning Emacs.  At this stage, we would be nuts
trying to.  Emacs, at the level of insdel.c, is stable, has been for a
long time.  We should only make there localized changes in response to
localized problems that are revealed at that level.  In the case in
point, the problem is revealed at a much higher level, so solving it
in insdel.c is simply wrong, because that will destabilize Emacs for
years to come.  We cannot afford that, as the "Emacs cloud" is too
large, and the number of people who understand these internals is too
small.

> > My interpretation of these two variables is that they are two hooks
> > provided for different kinds of features, because hooking into both
> > should not generally be required.  It should suffice for an
> > application that wants to react to a change in a buffer to hook into
> > after-change-functions only.
> 
> No.  A program (such as CC Mode) reacts to a _change_, not merely to
> what a buffer looks like after a change.  A buffer change loses
> information, so in the general case, any required info needs to be
> recorded by before-change-functions before it gets lost in the change,
> so that it can be used by after-change-functions.

And yet you had no problems until now.  This particular use case is
not about some arbitrary buffer change, it is about replacing the
whole buffer with an updated contents of the file.  We don't need to
consider any other use cases, because we are not aware of problems in
those cases.

> As a concrete example of this, suppose we have this in a buffer:
> 
>     #define foo() first line \
>                   second line \
> 	          third line \
> 	          fourth line
> 
> , and the change consists of deleting the backslash on L2.
> before-change-functions will have noted that all four lines are in the
> "active area".  after-change-functions unassisted would merely see that
> the "active area" consists of L1 and L2.  The info from before-change
> enables after-change to operate on the entire four lines.

You could simply discard the information for all the 4 lines, and be
done.  It is more important to be correct than to be optimal.

But anyway, I believe the case in point has nothing to do with this
example.  Right?

> > But even if I agree, for the sake of argument, with your
> > interpretation, let's put this issue into a proper perspective, okay?
> > We have a single major mode (albeit a very important one, one that I
> > use every day) that under very specific conditions apparently fails to
> > discard its caches, ....
> 
> Being precise, two critical variables were dirty store from the previous
> invocation of c-after-change, not having been set in the missing call to
> before-change-functions.

I still don't understand why you couldn't clear all such variables in
this case.  The entire buffer text has been replaced, why keep
anything you had before?

> > .... because its design assumed calls to these two hooks will always
> > be balanced.  As a solution, you are proposing a change in a very
> > low-level and delicate part of Emacs, which means significant changes
> > to code that was basically unchanged for more than 20, if not 30
> > years.
> 
> prepare_to_modify buffer has been modified lots of times in recent
> years.  (I count six modifications since 2014-01.)

I said "basically unchanged".  Trivial refactoring doesn't count.  And
any changes in this function were in response to issues common to all
the callers.  The case in point isn't such a case.

> > This code is involved in almost every operation on buffer
> > text, and so changes you propose will necessarily cause ripples all
> > over Emacs.  Just look what the code you propose to change does:
> 
> >   . call barf-if-buffer-read-only
> >   . set the buffer's redisplay flag
> >   . affect the undo recording
> >   . save the region when select-active-regions is non-nil
> >   . sets deactivate-mark non-nil
> 
> I'm not proposing to change any of that at all.  What I'm proposing is
> strictly limited, and could be accompished in two steps, as follows:
> 
> 1. (Pure refactoring).  Remove the call to signal_before_change from
> prepare_to_modify_buffer.  Insert an explicit call to s_b_c after each
> invocation of p_t_m_b.  Restore the check on inhibit_modification_hooks
> in s_b_c.
> 
> 2. Where a call to signal_buffer_change is within an "if (prepare) ..."
> construct, move it to after that construct, so that
> 
>     if (prepare)
>       {
>         prepare_to_modify_buffer (...);
> 	signal_after_change (...);
>       }
> 
> would become
> 
>     if (prepare)
>       prepare_to_modify_buffer (...);
>     signal_after_change (...);

See, that's the part that scares me.  You are proposing to run code
where we didn't run it before.  Did you look at what
signal_after_change does?  It doesn't just call
after-change-functions, it does much more.

> > Can you imagine how much Lisp code and basic features will be affected
> > by calling this where we never did before?  All that for the benefit
> > of a single major mode that fails in a single, albeit important use
> > case?
> 
> > I'm sorry, but that makes very little sense to me.
> 
> Please reconsider carefully the concrete proposal I've made (above) and
> judge whether it will really affect very much at all.

Your proposal doesn't take care of my fears.

> I can foresee that nothing will happen except the desired
> invocations of before-change-functions being made.

We will have to agree to disagree about this.

> I'm not entirely sure that only CC Mode will be helped here.  The value
> of before-change-functions in many major modes contains the function
> syntax-ppss-flush-cache.  There is a good chance that some call of, say,
> del_range_byte is going to leave the syntax-ppss cache stale and
> invalid, a difficult situation to diagnose.

I would have to see very specific evidence to that, not just
theoretical possibilities.  And even then, the proposed change touches
much more than just before-change-functions.

> > What does it do in each one of them, in the specific use case reported
> > in the named bugs?
> 
> It should calculate the two variables c-new-BEG and c-new-END (which
> bound the active region) in c-before-change, and these get modified in
> c-after-change.

Sorry, I don't understand.  Why can't you compute these two values in
the c-after-change?  And if you can't, why calling c-before-change
when REPLACE is non-nil didn't fix that?  Once again, we are talking
about reverting the entire buffer, so any intermediate deletions and
insertions aren't important.

> In the bug situation, these variables simply held stale values from
> the previous c-after-change call (which was from transpose-lines).
> Specifically, c-after-change modified c-new-END by subtracting
> old-len.  This happened to make c-new-END < c-new-BEG.  So a
> subsequent re-search-forward invocation had the limit on the wrong
> side of point and threw an error.

Why can't this error be caught and interpreted as a sign that the
cached values are wrong and need to be recomputed?

> > And why isn't it enough to make only the change you proposed in part 1
> > of your report?
> 
> I tried that, but it didn't work.  With the help of gdb, it was clear
> that the missing before-change-functions came from an invocation of
> del_range_byte with `prepare' false, rather than directly from
> Finsert_file_contents.

So if that single call is with 'prepare' set to true (when both VISIT
and REPLACE are non-nil), the problem would have been solved?

> > 2) Can this problem be fixed in CC Mode itself, without touching
> > either insert-file-contents or insdel.c functions?
> 
> I honestly don't know.  That would require extensive redesign if it's
> possible.  That would need something like creating a new cache to
> hold the information for the entire buffer which is currently determined
> in c-before-change.  A simple workaround would be to ignore (i.e. not
> process) an out of sequence invocation of c-after-change, but that's
> hardly ideal.  I suspect I'm going to have to do that anyway in
> standalone CC Mode.

If you are going to have to do that anyway, why do we have to consider
such low-level changes?

Btw, there's also a possibility for CC Mode to define its own
revert-buffer function.  That function could be a thin wrapper around
revert-buffer, and could do in the wrapping code whatever you think is
missing in insert-file-contents, like forcefully calling
before-change-functions.  That would still be better than messing with
insdel.c, IMO.

> > 3) If the answer to 2) above is a categorical NO (but please provide
> > enough arguments so we could be very sure it is that), then I _might_
> > be convinced to consider changes to insert-file-contents only, and
> > only for the case when both VISIT and REPLACE are non-nil.  That's
> > because I think this combination is only used by revert-buffer and
> > similar functionality (if someone knows about other callers that do
> > this, please holler), ....
> 
> The actual operation was C-x C-f where the file was already visited in
> Emacs, but had been modified outside of Emacs, so Finsert_file_contents
> went through the code which attempts to preserve markers, etc.

That's what revert-buffer does, it calls insert-file-contents with
both VISIT and REPLACE non-nil.  And that's the use case we are
talking about, right?

> > .... so the ripples will be not as wide as if we mess with insdel.c.
> > (Still, even this possibility scares the living s**t out of me; it
> > should do that to you as well.)  To this end, please tell which calls
> > to del_range_byte in insert-file-contents are involved with this use
> > case and cause trouble to CC Mode, and maybe we could change only
> > those, in addition to the 'if' clause that guards the call to
> > before-change-functions.
> 
> The del_range_byte call which I caught with gdb last night was, I think,
> the one at fileio.c L4037.  I don't know the code well enough to say
> that that's the only one which might trigger.

If changing that one alone solves the problem, we don't need to
consider any others.

Thanks.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 18:11     ` Eli Zaretskii
@ 2016-07-31 18:52       ` Eli Zaretskii
  2016-07-31 19:08         ` Eli Zaretskii
  2016-07-31 19:20       ` Noam Postavsky
  2016-07-31 21:26       ` Alan Mackenzie
  2 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-07-31 18:52 UTC (permalink / raw)
  To: acm; +Cc: ofv, rcopley, emacs-devel

> Date: Sun, 31 Jul 2016 21:11:32 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> 
> > The del_range_byte call which I caught with gdb last night was, I think,
> > the one at fileio.c L4037.  I don't know the code well enough to say
> > that that's the only one which might trigger.
> 
> If changing that one alone solves the problem, we don't need to
> consider any others.

Actually, I think we need to change all 3 of those calls, since they
all handle the same situation, with minor differences.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 17:28   ` Alan Mackenzie
  2016-07-31 18:11     ` Eli Zaretskii
@ 2016-07-31 18:55     ` Stefan Monnier
  2016-07-31 19:26       ` Eli Zaretskii
  2016-07-31 19:33       ` Alan Mackenzie
  2016-07-31 19:21     ` Eli Zaretskii
  2 siblings, 2 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-07-31 18:55 UTC (permalink / raw)
  To: emacs-devel

>     These hook variables let you arrange to take notice of ALL changes
>     in ALL buffers.  [My emphasis]
>
> Your interpretation of that seems to be that each buffer change will
> call _at least_ one of before-... and after-..., but not necessarily
> both.  That doesn't seem sensible to me.

I fully agree that if you only use before-change-functions (or only use
after-change-functions), your hook function should see *all* changes.

This is an important property and if there are places where this is not
the case, we should fix them.

> No.  A program (such as CC Mode) reacts to a _change_, not merely to
> what a buffer looks like after a change.

But here we have a problem: I don't think that
before/after-change-functions should be always be properly paired, which
IIUC is a property that CC-mode relies on.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 18:52       ` Eli Zaretskii
@ 2016-07-31 19:08         ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-07-31 19:08 UTC (permalink / raw)
  To: acm; +Cc: ofv, rcopley, emacs-devel

> Date: Sun, 31 Jul 2016 21:52:04 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> 
> > Date: Sun, 31 Jul 2016 21:11:32 +0300
> > From: Eli Zaretskii <eliz@gnu.org>
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> > 
> > > The del_range_byte call which I caught with gdb last night was, I think,
> > > the one at fileio.c L4037.  I don't know the code well enough to say
> > > that that's the only one which might trigger.
> > 
> > If changing that one alone solves the problem, we don't need to
> > consider any others.
> 
> Actually, I think we need to change all 3 of those calls, since they
> all handle the same situation, with minor differences.

Of course, I still think we should try solving this in CC Mode alone,
if reasonably possible.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 18:11     ` Eli Zaretskii
  2016-07-31 18:52       ` Eli Zaretskii
@ 2016-07-31 19:20       ` Noam Postavsky
  2016-07-31 21:26       ` Alan Mackenzie
  2 siblings, 0 replies; 189+ messages in thread
From: Noam Postavsky @ 2016-07-31 19:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, Alan Mackenzie, Richard Copley, Emacs developers

On Sun, Jul 31, 2016 at 2:11 PM, Eli Zaretskii <eliz@gnu.org> wrote:
>> 2. Where a call to signal_buffer_change is within an "if (prepare) ..."
>> construct, move it to after that construct, so that
>>
>>     if (prepare)
>>       {
>>         prepare_to_modify_buffer (...);
>>       signal_after_change (...);
>>       }
>>
>> would become
>>
>>     if (prepare)
>>       prepare_to_modify_buffer (...);
>>     signal_after_change (...);
>
> See, that's the part that scares me.  You are proposing to run code
> where we didn't run it before.  Did you look at what
> signal_after_change does?  It doesn't just call
> after-change-functions, it does much more.

Doesn't look like that much more to me. In addtion to
after-change-functions, it also calls overlay and text property
modification hooks. I don't see anything else.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 17:28   ` Alan Mackenzie
  2016-07-31 18:11     ` Eli Zaretskii
  2016-07-31 18:55     ` Stefan Monnier
@ 2016-07-31 19:21     ` Eli Zaretskii
  2 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-07-31 19:21 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Sun, 31 Jul 2016 17:28:04 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > And why isn't it enough to make only the change you proposed in part 1
> > of your report?
> 
> I tried that, but it didn't work.

Answering myself here: that didn't work because the part you proposed
to change, i.e.

  if (NILP (visit) && total > 0)
    {
      if (!NILP (BVAR (current_buffer, file_truename))
	  /* Make binding buffer-file-name to nil effective.  */
	  && !NILP (BVAR (current_buffer, filename))
	  && SAVE_MODIFF >= MODIFF)
	we_locked_file = true;
      prepare_to_modify_buffer (PT, PT, NULL);
    }

is not executed when REPLACE is non-nil.  So adding the condition you
suggested there will have no effect at all.

The relevant code is indeed the 3 calls to del_range_byte.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 18:55     ` Stefan Monnier
@ 2016-07-31 19:26       ` Eli Zaretskii
  2016-07-31 21:59         ` Stefan Monnier
  2016-07-31 19:33       ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-07-31 19:26 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Sun, 31 Jul 2016 14:55:32 -0400
> 
> >     These hook variables let you arrange to take notice of ALL changes
> >     in ALL buffers.  [My emphasis]
> >
> > Your interpretation of that seems to be that each buffer change will
> > call _at least_ one of before-... and after-..., but not necessarily
> > both.  That doesn't seem sensible to me.
> 
> I fully agree that if you only use before-change-functions (or only use
> after-change-functions), your hook function should see *all* changes.

The change in question is a replacement.  Emacs implements
replacements by a deletion followed by an insertion.  The question is:
do we need to call the before-change-functions for both the deletion
and the insertion, or do we need to call them only once for the
"replacement"?  We currently do the latter, i.e. call them only once.
If you think that's incorrect, please explain why.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 18:55     ` Stefan Monnier
  2016-07-31 19:26       ` Eli Zaretskii
@ 2016-07-31 19:33       ` Alan Mackenzie
  1 sibling, 0 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-07-31 19:33 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan.

On Sun, Jul 31, 2016 at 02:55:32PM -0400, Stefan Monnier wrote:
> >     These hook variables let you arrange to take notice of ALL changes
> >     in ALL buffers.  [My emphasis]

> > Your interpretation of that seems to be that each buffer change will
> > call _at least_ one of before-... and after-..., but not necessarily
> > both.  That doesn't seem sensible to me.

> I fully agree that if you only use before-change-functions (or only use
> after-change-functions), your hook function should see *all* changes.

Taking your parenthetical clause to be an essential part of your
sentence, this can only happen if all changes cause both before- and
after-change-functions to be called.  (A major mode "registering" which
one of before- or after- it wishes to see would be ludicrous.)

> This is an important property and if there are places where this is not
> the case, we should fix them.

I agree, it's what I'm proposing and trying to persuade Eli to accept.

> > No.  A program (such as CC Mode) reacts to a _change_, not merely to
> > what a buffer looks like after a change.

> But here we have a problem: I don't think that
> before/after-change-functions should be always be properly paired, which
> IIUC is a property that CC-mode relies on.

That appears to contradict your first paragraph.  CC Mode does indeed
rely on this proper pairing.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 18:11     ` Eli Zaretskii
  2016-07-31 18:52       ` Eli Zaretskii
  2016-07-31 19:20       ` Noam Postavsky
@ 2016-07-31 21:26       ` Alan Mackenzie
  2016-08-01 13:01         ` Stefan Monnier
  2016-08-01 13:07         ` Eli Zaretskii
  2 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-07-31 21:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, emacs-devel

Hello, Eli.

On Sun, Jul 31, 2016 at 09:11:32PM +0300, Eli Zaretskii wrote:
> > Date: Sun, 31 Jul 2016 17:28:04 +0000
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> >     This variable holds a list of functions to call before any buffer
> >     modification.

> > I can't see any sensible interpretation of "any ... modification" other
> > than "each and every modification".  I've been relying on this for many
> > years.

> You are forgetting that "buffer modifications" is not rigorously
> defined in Emacs.  Let me remind you that in so many places we pretend
> that no changes were made to a buffer, while in fact there were.

I've no problem with that, as long as each action either definitely is a
change or definitely isn't a change.  In the former case, it should run
the change hooks, in the latter case it shouldn't.  It's the halfway
house where half of the change hooks are run that I don't like.

> Given this fact, "any modification" has no meaning, beyond the
> tautological "modifications that Emacs developers decided to treat as
> such".

> IOW, what the code does, and has been doing for many moons, is in this
> case a de-facto _definition_ of what should be done.

Extending that principle ad absurdum, Emacs has no bugs at all, since
what it does is what it should do.

> > Looked at another way, how can it be sensible to call just one of these
> > hooks?

> I gave one such interpretation.

OK.  I don't agree with your principle, and I'm not convinced you do
either.  :-)

> > Like, if you were redesigning Emacs from scratch, are there any
> > categories of buffer modifications in which you would call only
> > after-change-functions, and not before-c-f?

> But we are not redesigning Emacs.  At this stage, we would be nuts
> trying to.  Emacs, at the level of insdel.c, is stable, has been for a
> long time.  We should only make there localized changes in response to
> localized problems that are revealed at that level.  In the case in
> point, the problem is revealed at a much higher level, so solving it
> in insdel.c is simply wrong, because that will destabilize Emacs for
> years to come.  We cannot afford that, as the "Emacs cloud" is too
> large, and the number of people who understand these internals is too
> small.

I'm in favour of fixing what is wrong, rather than implementing
workarounds somewhere else.  Workarounds are rarely fully satisfactory.
I think you would agree with me that having before- and after- hook
calls rigorously paired would be the ideal state - you haven't attempted
so far to argue that missing out a before-change-functions call is a
good thing.

Solving the problem in insdel.c is the Right Thing to do, because that
is where the cause of the problem lies.  You assert that the change I
propose would "destabilise Emacs for years to come", but you haven't
provided any analysis of my proposed change to support that assertion.
The hackers who built Emacs were and are of a higher quality than to
build such instability into Emacs.

> > > My interpretation of these two variables is that they are two hooks
> > > provided for different kinds of features, because hooking into both
> > > should not generally be required.  It should suffice for an
> > > application that wants to react to a change in a buffer to hook into
> > > after-change-functions only.
 
> > No.  A program (such as CC Mode) reacts to a _change_, not merely to
> > what a buffer looks like after a change.  A buffer change loses
> > information, so in the general case, any required info needs to be
> > recorded by before-change-functions before it gets lost in the change,
> > so that it can be used by after-change-functions.

> And yet you had no problems until now.  This particular use case is
> not about some arbitrary buffer change, it is about replacing the
> whole buffer with an updated contents of the file.

No.  The code does fancy things comparing the file to be revisited with
the current buffer contents, and only loading the minimum (in some
sense) portion of the file, so as to preserve markers, or something like
that.  In Richard Copley's recipe for bug #24094, an essential part was
the C-x C-t to transpose two lines before C-x C-s.  The complexities of
the transposition got remembered when reloading the file portion,
leading to the bug.

> We don't need to consider any other use cases, because we are not
> aware of problems in those cases.

If we fixed things the way I would like, we'd automatically fix these
other use cases without any effort.

> > As a concrete example of this, suppose we have this in a buffer:
> > 
> >     #define foo() first line \
> >                   second line \
> > 	          third line \
> > 	          fourth line
> > 
> > , and the change consists of deleting the backslash on L2.
> > before-change-functions will have noted that all four lines are in the
> > "active area".  after-change-functions unassisted would merely see that
> > the "active area" consists of L1 and L2.  The info from before-change
> > enables after-change to operate on the entire four lines.

> You could simply discard the information for all the 4 lines, and be
> done.  It is more important to be correct than to be optimal.

It is for correctness, not speed, that the information is recorded.
Over the last decade or so, there were quite a few bugs where jit-lock
delayed fontification messed up what had been (for 0.5s) correct, or
where typing a CR in the middle of construct messed fontification up, or
....  Please believe me, this recording of info in c-before-change was
not done just for its own sake.

For example, if a C++ template delimiter, which is marked with a
parenthesis syntax-table property, is about to be deleted, we ensure in
c-before-change that the matching delimiter is appropriately handled.

I'm not saying that CC Mode couldn't be redesigned not to use
before-change-functions, but it would be a massive amount of work which
wouldn't get us any closer to where we want CC Mode to be, and it would
be depressing unrewarding work.

> But anyway, I believe the case in point has nothing to do with this
> example.  Right?

No, the example offers a justification of why CC Mode needs both before-
and after-change-functions.

> > > But even if I agree, for the sake of argument, with your
> > > interpretation, let's put this issue into a proper perspective, okay?
> > > We have a single major mode (albeit a very important one, one that I
> > > use every day) that under very specific conditions apparently fails to
> > > discard its caches, ....

> > Being precise, two critical variables were dirty store from the previous
> > invocation of c-after-change, not having been set in the missing call to
> > before-change-functions.

> I still don't understand why you couldn't clear all such variables in
> this case.  The entire buffer text has been replaced, why keep
> anything you had before?

The entire buffer hasn't been replaced (see above).  Those variables
get initialised in c-before-change.  If the call to c-before-change is
missing, those variables will be dirty store.

> > > .... because its design assumed calls to these two hooks will always
> > > be balanced.  As a solution, you are proposing a change in a very
> > > low-level and delicate part of Emacs, which means significant changes
> > > to code that was basically unchanged for more than 20, if not 30
> > > years.
 
> > prepare_to_modify buffer has been modified lots of times in recent
> > years.  (I count six modifications since 2014-01.)

> I said "basically unchanged".  Trivial refactoring doesn't count.  And
> any changes in this function were in response to issues common to all
> the callers.  The case in point isn't such a case.

What I am proposing is only a little more than trivial refactoring.

> > > This code is involved in almost every operation on buffer
> > > text, and so changes you propose will necessarily cause ripples all
> > > over Emacs.  Just look what the code you propose to change does:

> > >   . call barf-if-buffer-read-only
> > >   . set the buffer's redisplay flag
> > >   . affect the undo recording
> > >   . save the region when select-active-regions is non-nil
> > >   . sets deactivate-mark non-nil
 
> > I'm not proposing to change any of that at all.  What I'm proposing is
> > strictly limited, and could be accompished in two steps, as follows:
 
> > 1. (Pure refactoring).  Remove the call to signal_before_change from
> > prepare_to_modify_buffer.  Insert an explicit call to s_b_c after each
> > invocation of p_t_m_b.  Restore the check on inhibit_modification_hooks
> > in s_b_c.
 
> > 2. Where a call to signal_buffer_change is within an "if (prepare) ..."
> > construct, move it to after that construct, so that
 
> >     if (prepare)
> >       {
> >         prepare_to_modify_buffer (...);
> > 	signal_after_change (...);
> >       }
 
> > would become
 
> >     if (prepare)
> >       prepare_to_modify_buffer (...);
> >     signal_after_change (...);

> See, that's the part that scares me.  You are proposing to run code
> where we didn't run it before.  Did you look at what
> signal_after_change does?  It doesn't just call
> after-change-functions, it does much more.

I'm proposing to run code designed to run before buffer changes before a
buffer change.  The code does a little more than call
before-change-functions but only a little:
(i) it runs first-change-hook;
(ii) it runs before-change-functions;
(iii) it runs report_overlay_modification (whatever that does).
(iv) it preserves *preserve_ptr as described in the comment.

I would be more worried that there are buffer modifications where
report_overlay_modification _doesn't_ get run.

> > > Can you imagine how much Lisp code and basic features will be affected
> > > by calling this where we never did before?  All that for the benefit
> > > of a single major mode that fails in a single, albeit important use
> > > case?

> > > I'm sorry, but that makes very little sense to me.
 
> > Please reconsider carefully the concrete proposal I've made (above) and
> > judge whether it will really affect very much at all.

> Your proposal doesn't take care of my fears.

I'm still trying to work out what they are, beyond a generalised
opposition to any change at this level of the code.

> > I can foresee that nothing will happen except the desired
> > invocations of before-change-functions being made.

> We will have to agree to disagree about this.

OK.  How about I implement what I've described, and we try it out?  If
it doesn't work, or it throws up non-trivial problems, it will be easy
enough to revert.

> > I'm not entirely sure that only CC Mode will be helped here.  The value
> > of before-change-functions in many major modes contains the function
> > syntax-ppss-flush-cache.  There is a good chance that some call of, say,
> > del_range_byte is going to leave the syntax-ppss cache stale and
> > invalid, a difficult situation to diagnose.

> I would have to see very specific evidence to that, not just
> theoretical possibilities.

Programs other than CC Mode use before-change-functions.  It would be
more effort to construct an actual failure than simply to fix the
problem.

> And even then, the proposed change touches much more than just
> before-change-functions.

> > > What does it do in each one of them, in the specific use case reported
> > > in the named bugs?

> > It should calculate the two variables c-new-BEG and c-new-END (which
> > bound the active region) in c-before-change, and these get modified in
> > c-after-change.

> Sorry, I don't understand.  Why can't you compute these two values in
> the c-after-change?

In the general case because information gets lost at a change; things
like where the beginning of a statement was, where deleted template
delimiters used to be, what the bounds of a macro or string used to be
(before backslashes were deleted).

Or are you suggesting I implement a special after-change handler for the
case when the before-change-functions was missing?  This would be
possible, but it would still be more work than ensuring that
before-change-functions actually gets called.

> And if you can't, why calling c-before-change
> when REPLACE is non-nil didn't fix that?  Once again, we are talking
> about reverting the entire buffer, so any intermediate deletions and
> insertions aren't important.

Again, the entire buffer wasn't replaced.  Read the comment in
Finsert_file_contents at ~L3697:

  /* If requested, replace the accessible part of the buffer
     with the file contents.  Avoid replacing text at the
     beginning or end of the buffer that matches the file contents;
     that preserves markers pointing to the unchanged parts.

> > In the bug situation, these variables simply held stale values from
> > the previous c-after-change call (which was from transpose-lines).
> > Specifically, c-after-change modified c-new-END by subtracting
> > old-len.  This happened to make c-new-END < c-new-BEG.  So a
> > subsequent re-search-forward invocation had the limit on the wrong
> > side of point and threw an error.

> Why can't this error be caught and interpreted as a sign that the
> cached values are wrong and need to be recomputed?

It's better (and less work) to determine them properly in the first
place.  Once we're in c-after-change, it's no longer possible to
calculate them properly in the general case.

> > > And why isn't it enough to make only the change you proposed in part 1
> > > of your report?

> > I tried that, but it didn't work.  With the help of gdb, it was clear
> > that the missing before-change-functions came from an invocation of
> > del_range_byte with `prepare' false, rather than directly from
> > Finsert_file_contents.

> So if that single call is with 'prepare' set to true (when both VISIT
> and REPLACE are non-nil), the problem would have been solved?

Yes, apart from all the other processing in prepare_to_modify_buffer
that the `prepare' flag being false is designed to avoid.

> > > 2) Can this problem be fixed in CC Mode itself, without touching
> > > either insert-file-contents or insdel.c functions?

> > I honestly don't know.  That would require extensive redesign if it's
> > possible.  That would need something like creating a new cache to
> > hold the information for the entire buffer which is currently determined
> > in c-before-change.  A simple workaround would be to ignore (i.e. not
> > process) an out of sequence invocation of c-after-change, but that's
> > hardly ideal.  I suspect I'm going to have to do that anyway in
> > standalone CC Mode.

> If you are going to have to do that anyway, why do we have to consider
> such low-level changes?

Because a proper fix is the Right Thing to do.  It's more satisfying,
works better, and eliminates other potential problems which haven't
shown up yet, or undiagnosed bugs caused by this which we haven't been
able to tie down.

> Btw, there's also a possibility for CC Mode to define its own
> revert-buffer function.  That function could be a thin wrapper around
> revert-buffer, and could do in the wrapping code whatever you think is
> missing in insert-file-contents, like forcefully calling
> before-change-functions.  That would still be better than messing with
> insdel.c, IMO.

Reverting the buffer is merely the recipe to reproduce the bug.  The bug
itself is c-before-change not being called.  It is likely to show up in
other circumstances if we don't fix it.

> > > 3) If the answer to 2) above is a categorical NO (but please provide
> > > enough arguments so we could be very sure it is that), then I _might_
> > > be convinced to consider changes to insert-file-contents only, and
> > > only for the case when both VISIT and REPLACE are non-nil.  That's
> > > because I think this combination is only used by revert-buffer and
> > > similar functionality (if someone knows about other callers that do
> > > this, please holler), ....
 
> > The actual operation was C-x C-f where the file was already visited in
> > Emacs, but had been modified outside of Emacs, so Finsert_file_contents
> > went through the code which attempts to preserve markers, etc.

> That's what revert-buffer does, it calls insert-file-contents with
> both VISIT and REPLACE non-nil.  And that's the use case we are
> talking about, right?

More or less.  C-x C-f also goes through these machinations in the case
described.

> > > .... so the ripples will be not as wide as if we mess with insdel.c.
> > > (Still, even this possibility scares the living s**t out of me; it
> > > should do that to you as well.)  To this end, please tell which calls
> > > to del_range_byte in insert-file-contents are involved with this use
> > > case and cause trouble to CC Mode, and maybe we could change only
> > > those, in addition to the 'if' clause that guards the call to
> > > before-change-functions.

> > The del_range_byte call which I caught with gdb last night was, I think,
> > the one at fileio.c L4037.  I don't know the code well enough to say
> > that that's the only one which might trigger.

> If changing that one alone solves the problem, we don't need to
> consider any others.

As I said, why not let me implement what I've suggested?  If it doesn't
work well enough, I can revert it.

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 19:26       ` Eli Zaretskii
@ 2016-07-31 21:59         ` Stefan Monnier
  2016-08-01 13:09           ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-07-31 21:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

>> I fully agree that if you only use before-change-functions (or only use
>> after-change-functions), your hook function should see *all* changes.
> The change in question is a replacement.  Emacs implements
> replacements by a deletion followed by an insertion.  The question is:
> do we need to call the before-change-functions for both the deletion
> and the insertion, or do we need to call them only once for the
> "replacement"?

Either way is fine, according to my interpretation of "should see *all*
changes".


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 21:26       ` Alan Mackenzie
@ 2016-08-01 13:01         ` Stefan Monnier
  2016-08-01 13:07         ` Eli Zaretskii
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-01 13:01 UTC (permalink / raw)
  To: emacs-devel

>> > As a concrete example of this, suppose we have this in a buffer:
>> > 
>> >     #define foo() first line \
>> >                   second line \
>> > 	          third line \
>> > 	          fourth line
>> > 
>> > , and the change consists of deleting the backslash on L2.
>> > before-change-functions will have noted that all four lines are in the
>> > "active area".  after-change-functions unassisted would merely see that
>> > the "active area" consists of L1 and L2.  The info from before-change
>> > enables after-change to operate on the entire four lines.

I think this can work at one condition: you need to make sure that it
also works if you get something like:

  b-c-f called on L2
  b-c-f called on L37
  a-c-f called on L2-L37

or

  b-c-f called on L2
  b-c-f called on L37
  a-c-f called on L2
  a-c-f called on L37

or

  b-c-f called on L2-L3
  a-c-f called on L2
  a-c-f called on L3

and other such variations.

> I'm not saying that CC Mode couldn't be redesigned not to use
> before-change-functions, but it would be a massive amount of work which
> wouldn't get us any closer to where we want CC Mode to be, and it would
> be depressing unrewarding work.

Switching to use syntax-propertize would likely solve this problem along
with various others and would be very rewarding.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 21:26       ` Alan Mackenzie
  2016-08-01 13:01         ` Stefan Monnier
@ 2016-08-01 13:07         ` Eli Zaretskii
  2016-08-01 16:53           ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-01 13:07 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Sun, 31 Jul 2016 21:26:35 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > IOW, what the code does, and has been doing for many moons, is in this
> > case a de-facto _definition_ of what should be done.
> 
> Extending that principle ad absurdum, Emacs has no bugs at all, since
> what it does is what it should do.

Which is true.  Of course, since Emacs developers are reasonable
people (with the possible exception of yours truly), the result is
also reasonable.

So I suggest that we abandon this semi-philosophical sub-thread, and
instead focus on the practical issue at hand.

> I'm in favour of fixing what is wrong, rather than implementing
> workarounds somewhere else.  Workarounds are rarely fully satisfactory.

I'm not suggesting a workaround.  I'm suggesting a fix for a design
flaw in CC Mode -- its assumption that before-change-functions and
after-change-functions are always invoked in balanced pairs.  CC Mode
must not depend on that assumption, because it's false.

> I think you would agree with me that having before- and after- hook
> calls rigorously paired would be the ideal state - you haven't attempted
> so far to argue that missing out a before-change-functions call is a
> good thing.

It might be ideal, but it's next to impossible in practice.  It would
prohibit or greatly complicate code that deals with buffer
modifications, because for various reasons that code might do the
changes piecemeal.

In practice, we need to make sure that every modification triggers at
least one call to before-change-functions and at least one call to
after-change-functions.  The numbers of these calls do not have to
match.

> Solving the problem in insdel.c is the Right Thing to do, because that
> is where the cause of the problem lies.  You assert that the change I
> propose would "destabilise Emacs for years to come", but you haven't
> provided any analysis of my proposed change to support that assertion.

I had my share of hacking that code and its callers.  It's impossible
to convey everything I learned while doing that in a discussion such
as this one.  I say more about this below.  If that's still not
enough, you will have to trust me on that.

> The hackers who built Emacs were and are of a higher quality than to
> build such instability into Emacs.

"Instability" here means that various features that expect certain
things to happen will instead see unexpected situations.  Emacs will
still work and be stable as a program (i.e. won't crash and probably
won't corrupt your buffers).  But various functions will exhibit more
or less subtle bugs and misfeatures.

> The code does fancy things comparing the file to be revisited with
> the current buffer contents, and only loading the minimum (in some
> sense) portion of the file, so as to preserve markers, or something like
> that.

It's an internal optimization in insert-file-contents that CC Mode
doesn't have to follow, if doing that is painful.  Of course, if you
can reliably invalidate only the cached values that refer to the
region actually replaced, it's better.  But it's only an optimization.

> Please believe me, this recording of info in c-before-change was not
> done just for its own sake.

I believe you.  Just don't assume that there will be a c-before-change
call for each c-after-change call, that's all.

Specifically, in the case in point, I believe that the "unbalanced"
call to c-after-change clearly tells you that text has been deleted,
so I think it should be enough for you to do the job of the "missing"
c-before-change call as well.

> > I said "basically unchanged".  Trivial refactoring doesn't count.  And
> > any changes in this function were in response to issues common to all
> > the callers.  The case in point isn't such a case.
> 
> What I am proposing is only a little more than trivial refactoring.

No, it's far from that.  It fundamentally changes the list of things
that are done in many operations that modify buffers in various ways,
and the order in which these things are done.  We shouldn't make such
changes at this point in Emacs development, unless we identify a clear
bug that affects all the callers of these functions.

This case is not such a case.  It is a case of a single Lisp package
that made incorrect assumptions about the way the modification hooks
are called.  So the right place to fix this is in that Lisp package.

> > >     if (prepare)
> > >       prepare_to_modify_buffer (...);
> > >     signal_after_change (...);
> > 
> > See, that's the part that scares me.  You are proposing to run code
> > where we didn't run it before.  Did you look at what
> > signal_after_change does?  It doesn't just call
> > after-change-functions, it does much more.
> 
> I'm proposing to run code designed to run before buffer changes before a
> buffer change.

You are confusingly using signal_after_change and signal_before_change
interchangeably, so there's probably quite a lot of misunderstanding.

If you meant this:

     if (prepare)
       prepare_to_modify_buffer (...);
     signal_before_change (...);

then I don't see how it could work, because prepare_to_modify_buffer
computes one of the arguments to signal_before_change, so calling the
latter without calling the former is not really a good idea.  (This is
just one example of the many subtleties hiding in these seemingly
simple, almost innocently looking functions we have in insdel.c.)

> I'm still trying to work out what they are, beyond a generalised
> opposition to any change at this level of the code.

Without a good reason, yeah, that's pretty much it.

It's not some paranoia, mind you: I've been working on fixing quite a
few subtle bugs which originated due to such changes for the last few
years, so I know what I'm talking about.  Please trust my experience
and the conclusions I drew from it.

> > We will have to agree to disagree about this.
> 
> OK.  How about I implement what I've described, and we try it out?  If
> it doesn't work, or it throws up non-trivial problems, it will be easy
> enough to revert.

Sorry, no.  What I'd like you to try instead is eliminate from CC Mode
the incorrect assumption about pairwise calls to before- and
after-change-functions.  That is the correct way towards solving this
problem.  It is unwise to waste your time (and mine) on trying to
solve this by changing how modification hooks are called, because
that's not where the problem is.

> Programs other than CC Mode use before-change-functions.  It would be
> more effort to construct an actual failure than simply to fix the
> problem.

But before-change-functions _are_ being called in the scenario of the
bugs we are discussing.  They just aren't balanced with calls to
after-change-functions, that's all.  See, in this fragment of
insert-file-contents:

      if (same_at_end != same_at_start)
	{
	  invalidate_buffer_caches (current_buffer,
				    BYTE_TO_CHAR (same_at_start),
				    same_at_end_charpos);
	  del_range_byte (same_at_start, same_at_end, 0);
	  temp = GPT;
	  eassert (same_at_start == GPT_BYTE);
	  same_at_start = GPT_BYTE;
	}
      else
	{
	  temp = same_at_end_charpos;
	}
      /* Insert from the file at the proper position.  */
      SET_PT_BOTH (temp, same_at_start);
      same_at_start_charpos
	= buf_bytepos_to_charpos (XBUFFER (conversion_buffer),
				  same_at_start - BEGV_BYTE
				  + BUF_BEG_BYTE (XBUFFER (conversion_buffer)));
      eassert (same_at_start_charpos == temp - (BEGV - BEG));
      inserted_chars
	= (buf_bytepos_to_charpos (XBUFFER (conversion_buffer),
				   same_at_start + inserted - BEGV_BYTE
				  + BUF_BEG_BYTE (XBUFFER (conversion_buffer)))
	   - same_at_start_charpos);
      /* This binding is to avoid ask-user-about-supersession-threat
	 being called in insert_from_buffer (via in
	 prepare_to_modify_buffer).  */
      specbind (intern ("buffer-file-name"), Qnil);
      insert_from_buffer (XBUFFER (conversion_buffer),
			  same_at_start_charpos, inserted_chars, 0);

the before-change-functions are called from insert_from_buffer.  So
it's not like the replacement would be missed by the
before-change-functions.

IOW, your problem is not that before-change-functions are not called
in this specific scenario to indicate the replacement.  Your problem
is that the number of calls to before-change-functions doesn't match
the number of calls to after-change-functions, because del_range_byte
calls after-change-functions one extra time.  And that's the problem
which needs to be fixed, and it should be fixed in CC Mode, because
assuming these calls are balanced is simply wrong.

> > > It should calculate the two variables c-new-BEG and c-new-END (which
> > > bound the active region) in c-before-change, and these get modified in
> > > c-after-change.
> > 
> > Sorry, I don't understand.  Why can't you compute these two values in
> > the c-after-change?
> 
> In the general case because information gets lost at a change; things
> like where the beginning of a statement was, where deleted template
> delimiters used to be, what the bounds of a macro or string used to be
> (before backslashes were deleted).

I'm sure CC Mode is well equipped to recalculate all of these if
needed.  It does that when a file is first visited.

> Or are you suggesting I implement a special after-change handler for the
> case when the before-change-functions was missing?

Could be.  I don't know CC Mode well enough to propose specific
solutions.

> This would be possible, but it would still be more work than
> ensuring that before-change-functions actually gets called.

As I show above, before-change-functions _do_ get called by
insert-file-contents in this scenario.

> > If you are going to have to do that anyway, why do we have to consider
> > such low-level changes?
> 
> Because a proper fix is the Right Thing to do.

Well, we clearly disagree about that.  I think there's no problem in
insdel.c or its callers, and the cause of this bug is the incorrect
assumption in CC Mode that before- and after-change-functions will be
called in balanced pairs.  So from my POV, TRT would be to eliminate
that assumption, which should make CC Mode more robust in the long
run, as I'm not sure this is the only case where that assumption
breaks.

> Reverting the buffer is merely the recipe to reproduce the bug.  The bug
> itself is c-before-change not being called.

See above: it _is_ being called, from insert_from_buffer.

> As I said, why not let me implement what I've suggested?  If it doesn't
> work well enough, I can revert it.

Because it will waste time and efforts on a way towards a dead end.

Thanks.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 21:59         ` Stefan Monnier
@ 2016-08-01 13:09           ` Eli Zaretskii
  2016-08-01 14:36             ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-01 13:09 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: emacs-devel@gnu.org
> Date: Sun, 31 Jul 2016 17:59:32 -0400
> 
> >> I fully agree that if you only use before-change-functions (or only use
> >> after-change-functions), your hook function should see *all* changes.
> > The change in question is a replacement.  Emacs implements
> > replacements by a deletion followed by an insertion.  The question is:
> > do we need to call the before-change-functions for both the deletion
> > and the insertion, or do we need to call them only once for the
> > "replacement"?
> 
> Either way is fine, according to my interpretation of "should see *all*
> changes".

Then I think we are fine, give or take a couple of minor changes that
might be needed in insert-file-contents.

Btw, it looks like insert-file-contents deliberately doesn't call
before-change-functions if nothing was inserted, even if some text was
deleted.  I wonder why.  The way the code is written, it cannot be a
coincidence.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 13:09           ` Eli Zaretskii
@ 2016-08-01 14:36             ` Stefan Monnier
  2016-08-01 14:48               ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-01 14:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

> Btw, it looks like insert-file-contents deliberately doesn't call
> before-change-functions if nothing was inserted, even if some text was
> deleted.

Sounds like a bug.

> I wonder why.  The way the code is written, it cannot be a
> coincidence.

Coincidence or not, the b-c-f should we warned about the change.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 14:36             ` Stefan Monnier
@ 2016-08-01 14:48               ` Eli Zaretskii
  2016-08-01 15:28                 ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-01 14:48 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> Date: Mon, 01 Aug 2016 10:36:42 -0400
> Cc: emacs-devel@gnu.org
> 
> > Btw, it looks like insert-file-contents deliberately doesn't call
> > before-change-functions if nothing was inserted, even if some text was
> > deleted.
> 
> Sounds like a bug.
> 
> > I wonder why.  The way the code is written, it cannot be a
> > coincidence.
> 
> Coincidence or not, the b-c-f should we warned about the change.

But then why do we use a similar logic for after-change-functions?
Like this:

  if (inserted > 0 && total > 0
      && (NILP (visit) || !NILP (replace)))
    {
      signal_after_change (PT, 0, inserted);
      update_compositions (PT, PT, CHECK_BORDER);
    }

IOW, we don't call after-change-functions if nothing was inserted.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 14:48               ` Eli Zaretskii
@ 2016-08-01 15:28                 ` Stefan Monnier
  0 siblings, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-01 15:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

> But then why do we use a similar logic for after-change-functions?
> Like this:

>   if (inserted > 0 && total > 0
>       && (NILP (visit) || !NILP (replace)))
>     {
>       signal_after_change (PT, 0, inserted);
>       update_compositions (PT, PT, CHECK_BORDER);
>     }

> IOW, we don't call after-change-functions if nothing was inserted.

Sounds like a bug as well (unless it's called elsewhere in that case).
It's OK to skip calling a-c-f if we did not insert anything *and* did
not remove anything either.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 12:16 Unbalanced change hooks (part 2) Alan Mackenzie
  2016-07-31 13:58 ` Noam Postavsky
  2016-07-31 15:03 ` Eli Zaretskii
@ 2016-08-01 16:38 ` Richard Stallman
  2016-08-02 10:15   ` Alan Mackenzie
  2 siblings, 1 reply; 189+ messages in thread
From: Richard Stallman @ 2016-08-01 16:38 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > There are several functions in .../src/insdel.c which have a parameter
  > `prepare'.  The meaning of `prepare' is "direct the function to call
  > prepare_to_modify_buffer" (YUCK!).

Why do you say "yuck" to that?

I'm not saying it can't have problems, or that you can't
think of some change for the better.  However, to merit "yuck",
it would have to be grossly and conspicuously bad.

-- 
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 13:07         ` Eli Zaretskii
@ 2016-08-01 16:53           ` Alan Mackenzie
  2016-08-01 17:15             ` Alan Mackenzie
                               ` (2 more replies)
  0 siblings, 3 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-01 16:53 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, emacs-devel

Hello, Eli.

On Mon, Aug 01, 2016 at 04:07:50PM +0300, Eli Zaretskii wrote:
> > Date: Sun, 31 Jul 2016 21:26:35 +0000
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

[ .... ]

> > I'm in favour of fixing what is wrong, rather than implementing
> > workarounds somewhere else.  Workarounds are rarely fully satisfactory.

> I'm not suggesting a workaround.  I'm suggesting a fix for a design
> flaw in CC Mode -- its assumption that before-change-functions and
> after-change-functions are always invoked in balanced pairs.  CC Mode
> must not depend on that assumption, because it's false.

The flaw lies between the Emacs core and the Elisp manual.  The latter
quite clearly implies that each buffer change is accompanied by a single
before-change-functions call and a single after-change-functions call.

If Emacs is not going to be fixed to match its spec, then the doc will
need to be changed to match Emacs.  It will need to say, in some fashion,
that the two change hooks are called indeterminately.

[ .... ]

> In practice, we need to make sure that every modification triggers at
> least one call to before-change-functions and at least one call to
> after-change-functions.  The numbers of these calls do not have to
> match.

And in such calls, what are the parameters BEG, END, and OLD-LEN supposed
to mean?

> I had my share of hacking that code [insdel.c] and its callers.  It's
> impossible to convey everything I learned while doing that in a
> discussion such as this one.  I say more about this below.  If that's
> still not enough, you will have to trust me on that.

OK.  In exchange, I'm asking you to trust me when I say that the sort of
change you're expecting in CC Mode is impractical - months of work,
rather than weeks.

[ .... ]

> Just don't assume that there will be a c-before-change call for each
> c-after-change call, that's all.

What you seem to be saying is that before-change-functions isn't very
useful.  Since lots of packages use it, you seem to be saying that these
packages are broken, just as CC Mode is broken.

> Specifically, in the case in point, I believe that the "unbalanced"
> call to c-after-change clearly tells you that text has been deleted,
> so I think it should be enough for you to do the job of the "missing"
> c-before-change call as well.

No.  CC Mode also needs to know what was there before the change.  It
cannot guess.  I think it's fair to ask you to suggest a way for CC Mode
to get that deleted buffer section, somehow.

It is a perfectly reasonable requirement for a generic piece of Lisp code
to be able to get full details of any buffer change.

I've had a few wierd ideas myself on this, one of the first being that CC
Mode will maintain a shadow buffer for each of its buffers.  The shadow
will be identical to the main buffer in all ways, apart from when changes
are under way.  After a buffer change, CC Mode will consult the shadow
buffer to see what used to be there, and then copy the change from the
main buffer to keep it up to date.  I don't think this is a good way to
go, so I'm asking you to suggest something better.

> > > I said "basically unchanged".  Trivial refactoring doesn't count.  And
> > > any changes in this function were in response to issues common to all
> > > the callers.  The case in point isn't such a case.

> > What I am proposing is only a little more than trivial refactoring.

> No, it's far from that.  It fundamentally changes the list of things
> that are done in many operations that modify buffers in various ways,
> and the order in which these things are done.  We shouldn't make such
> changes at this point in Emacs development, unless we identify a clear
> bug that affects all the callers of these functions.

> This case is not such a case.  It is a case of a single Lisp package
> that made incorrect assumptions about the way the modification hooks
> are called.  So the right place to fix this is in that Lisp package.

Here is a list of lisp files which use before-change-functions.
Currently all of them are broken due to the unreliability of
before-change-functions:

./wid-edit.el:1292:  (add-hook 'before-change-functions 'widget-before-change nil t)
./emacs-lisp/syntax.el:495:             (add-hook 'before-change-functions
./whitespace.el:2184:    (add-hook 'before-change-functions #'whitespace-buffer-changed nil t)
./allout-widgets.el:594:        (add-hook 'before-change-functions 'allout-widgets-before-change-handler
./allout-widgets.el:741:          (add-hook 'before-change-functions
./obsolete/lazy-lock.el:591:    (add-hook 'before-change-functions 'lazy-lock-arrange-before-change nil t))
./org/org-table.el:3954:  (add-hook 'before-change-functions 'org-table-remove-rectangle-highlight))
./allout.el:2049:      (add-hook 'before-change-functions 'allout-before-change-handler nil t)
./progmodes/cc-mode.el:641:  (add-hook 'before-change-functions 'c-before-change nil t)
./progmodes/js.el:3740:  (add-hook 'before-change-functions #'js--flush-caches t t)
./progmodes/compile.el:2115:  (add-hook 'before-change-functions 'compilation--flush-parse nil t)
./cedet/semantic/grammar.el:1347:  (add-hook 'before-change-functions
./textmodes/tex-mode.el:707:      (add-hook 'before-change-functions
./textmodes/sgml-mode.el:926:        (add-hook 'before-change-functions
./emulation/viper-cmd.el:2307:  (add-hook 'before-change-functions 'viper-before-change-sentinel t)

[ .... ]

> > I'm still trying to work out what they are, beyond a generalised
> > opposition to any change at this level of the code.

> Without a good reason, yeah, that's pretty much it.

> It's not some paranoia, mind you: I've been working on fixing quite a
> few subtle bugs which originated due to such changes for the last few
> years, so I know what I'm talking about.  Please trust my experience
> and the conclusions I drew from it.

Please tell me how CC Mode can get full details of any buffer change,
then I'll be (reasonably) happy.

[ .... ]

> What I'd like you to try instead is eliminate from CC Mode the
> incorrect assumption about pairwise calls to before- and
> after-change-functions.  That is the correct way towards solving this
> problem.

CC Mode needs full details of all buffer changes.  Redesigning it so that
it doesn't doesn't bear thinking about - it would be far more work than
making the change hooks get called properly.

How about the following idea: we deprecate before-change-functions, which
is broken anyway, and isn't going to get fixed.  Functions in
after-change-functions would somehow get access to the old deleted
portion of the buffer, complete with text properties, overlays, ...?
This shouldn't be too hard, given that such stuff is stored in the undo
list anyway, even though in an unsuitable form.

> > Programs other than CC Mode use before-change-functions.  It would be
> > more effort to construct an actual failure than simply to fix the
> > problem.

> But before-change-functions _are_ being called in the scenario of the
> bugs we are discussing.  They just aren't balanced with calls to
> after-change-functions, that's all.

No.  In the scenario of bug #24094 there was no call to
before-change-functions whatsoever.  (Discovered by instrumenting
c-before-change and c-after-change for edebug.)

> See, in this fragment of insert-file-contents:

>       if (same_at_end != same_at_start)
> 	{
> 	  invalidate_buffer_caches (current_buffer,
> 				    BYTE_TO_CHAR (same_at_start),
> 				    same_at_end_charpos);
> 	  del_range_byte (same_at_start, same_at_end, 0);
> 	  temp = GPT;
> 	  eassert (same_at_start == GPT_BYTE);
> 	  same_at_start = GPT_BYTE;
> 	}
>       else
> 	{
> 	  temp = same_at_end_charpos;
> 	}
>       /* Insert from the file at the proper position.  */
>       SET_PT_BOTH (temp, same_at_start);
>       same_at_start_charpos
> 	= buf_bytepos_to_charpos (XBUFFER (conversion_buffer),
> 				  same_at_start - BEGV_BYTE
> 				  + BUF_BEG_BYTE (XBUFFER (conversion_buffer)));
>       eassert (same_at_start_charpos == temp - (BEGV - BEG));
>       inserted_chars
> 	= (buf_bytepos_to_charpos (XBUFFER (conversion_buffer),
> 				   same_at_start + inserted - BEGV_BYTE
> 				  + BUF_BEG_BYTE (XBUFFER (conversion_buffer)))
> 	   - same_at_start_charpos);
>       /* This binding is to avoid ask-user-about-supersession-threat
> 	 being called in insert_from_buffer (via in
> 	 prepare_to_modify_buffer).  */
>       specbind (intern ("buffer-file-name"), Qnil);
>       insert_from_buffer (XBUFFER (conversion_buffer),
> 			  same_at_start_charpos, inserted_chars, 0);

> the before-change-functions are called from insert_from_buffer.  So
> it's not like the replacement would be missed by the
> before-change-functions.

It was missed in the recipe for bug #24094.  For an atomic user action
(namely C-x C-f test.c++ followed by typing "yes" to the prompt to reload
the file) there was no invocation of before-change-functions and one of
after-change-functions.  This is the bug I am complaining of.

[ .... ]

> > > > It should calculate the two variables c-new-BEG and c-new-END (which
> > > > bound the active region) in c-before-change, and these get modified in
> > > > c-after-change.

> > > Sorry, I don't understand.  Why can't you compute these two values in
> > > the c-after-change?

> > In the general case because information gets lost at a change; things
> > like where the beginning of a statement was, where deleted template
> > delimiters used to be, what the bounds of a macro or string used to be
> > (before backslashes were deleted).

> I'm sure CC Mode is well equipped to recalculate all of these if
> needed.  It does that when a file is first visited.

An empty buffer is a fully defined state.  A buffer immediately following
a deletion is in an undefined state, which requires to know what was
deleted to make it defined again.

[ .... ]

> > Because a proper fix is the Right Thing to do.

> Well, we clearly disagree about that.  I think there's no problem in
> insdel.c or its callers, and the cause of this bug is the incorrect
> assumption in CC Mode that before- and after-change-functions will be
> called in balanced pairs.  So from my POV, TRT would be to eliminate
> that assumption, which should make CC Mode more robust in the long
> run, as I'm not sure this is the only case where that assumption
> breaks.

Please provide some means by which CC Mode has access to the full details
of a buffer change.  That's all I'm asking for now (even if I'm getting a
bit repetitive).

[ .... ]

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 16:53           ` Alan Mackenzie
@ 2016-08-01 17:15             ` Alan Mackenzie
  2016-08-01 19:39               ` Eli Zaretskii
  2016-08-01 19:37             ` Eli Zaretskii
  2016-08-02 14:39             ` Stefan Monnier
  2 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-01 17:15 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, emacs-devel

Hello again, Eli.

On Mon, Aug 01, 2016 at 04:53:23PM +0000, Alan Mackenzie wrote:

[ .... ]

> Please provide some means by which CC Mode has access to the full details
> of a buffer change.  That's all I'm asking for now (even if I'm getting a
> bit repetitive).

How about the following idea: we create a special purpose undo list
separate from the existing one.  Every change is recorded on this list,
regardless of whether or not main undo is disabled.  After each
invocation of after-change-functions the list is emptied.

    (defmacro with-change-undone (&rest forms) ...)

An after-change-function can invoke the macro `with-change-undone' which
would undo the changes, execute the &rest forms, then redo the changes.

Surely this would satisfy both of us, no?

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 16:53           ` Alan Mackenzie
  2016-08-01 17:15             ` Alan Mackenzie
@ 2016-08-01 19:37             ` Eli Zaretskii
  2016-08-02 14:39             ` Stefan Monnier
  2 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-01 19:37 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Mon, 1 Aug 2016 16:53:23 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > I'm not suggesting a workaround.  I'm suggesting a fix for a design
> > flaw in CC Mode -- its assumption that before-change-functions and
> > after-change-functions are always invoked in balanced pairs.  CC Mode
> > must not depend on that assumption, because it's false.
> 
> The flaw lies between the Emacs core and the Elisp manual.  The latter
> quite clearly implies that each buffer change is accompanied by a single
> before-change-functions call and a single after-change-functions call.

I don't mind making the manual more explicit on this.  But doing so
won't fix the problem at hand.

> > In practice, we need to make sure that every modification triggers at
> > least one call to before-change-functions and at least one call to
> > after-change-functions.  The numbers of these calls do not have to
> > match.
> 
> And in such calls, what are the parameters BEG, END, and OLD-LEN supposed
> to mean?

That depends on whether the changes are insertions or deletions.  I
thought it was quite clear from the documentation, but if not, we can
spell that out better as well.

> > I had my share of hacking that code [insdel.c] and its callers.  It's
> > impossible to convey everything I learned while doing that in a
> > discussion such as this one.  I say more about this below.  If that's
> > still not enough, you will have to trust me on that.
> 
> OK.  In exchange, I'm asking you to trust me when I say that the sort of
> change you're expecting in CC Mode is impractical - months of work,
> rather than weeks.

I trust you.  I just hope you will find a simpler way of doing that,
after some thought and maybe more discussions.

> > Just don't assume that there will be a c-before-change call for each
> > c-after-change call, that's all.
> 
> What you seem to be saying is that before-change-functions isn't very
> useful.  Since lots of packages use it, you seem to be saying that these
> packages are broken, just as CC Mode is broken.

No, I don't think before-change-functions are useless, and I don't
know about any breakage of packages that use that hook.

> > Specifically, in the case in point, I believe that the "unbalanced"
> > call to c-after-change clearly tells you that text has been deleted,
> > so I think it should be enough for you to do the job of the "missing"
> > c-before-change call as well.
> 
> No.  CC Mode also needs to know what was there before the change.  It
> cannot guess.  I think it's fair to ask you to suggest a way for CC Mode
> to get that deleted buffer section, somehow.

The functions that delete text do call after-change-functions, and
those functions do get this information.  Or maybe I don't understand
what is it that you are asking.

> Here is a list of lisp files which use before-change-functions.
> Currently all of them are broken due to the unreliability of
> before-change-functions:

It depends how they are using this hook.

> Please tell me how CC Mode can get full details of any buffer change,
> then I'll be (reasonably) happy.

You will have to tell much more about your needs, for me to begin
being helpful on that level.  Right now, all I can say is that
after-change-functions provide that information, AFAIK.

> > But before-change-functions _are_ being called in the scenario of the
> > bugs we are discussing.  They just aren't balanced with calls to
> > after-change-functions, that's all.
> 
> No.  In the scenario of bug #24094 there was no call to
> before-change-functions whatsoever.

They were on my system, I saw in GDB signal_before_change being called
from that place in insert-file-contents.  I wonder how come you didn't.

> >       insert_from_buffer (XBUFFER (conversion_buffer),
> > 			  same_at_start_charpos, inserted_chars, 0);
> 
> > the before-change-functions are called from insert_from_buffer.  So
> > it's not like the replacement would be missed by the
> > before-change-functions.
> 
> It was missed in the recipe for bug #24094.

How can that be?  insert_from_buffer unconditionally calls
insert_from_buffer_1, which unconditionally calls
prepare_to_modify_buffer, which in turns calls signal_before_change.

> For an atomic user action (namely C-x C-f test.c++ followed by
> typing "yes" to the prompt to reload the file) there was no
> invocation of before-change-functions and one of
> after-change-functions.  This is the bug I am complaining of.

Then I guess we are not talking about the same situation, and some
more digging is in order.  I did reproduce this using the recipe in
those bugs.

> > > In the general case because information gets lost at a change; things
> > > like where the beginning of a statement was, where deleted template
> > > delimiters used to be, what the bounds of a macro or string used to be
> > > (before backslashes were deleted).
> 
> > I'm sure CC Mode is well equipped to recalculate all of these if
> > needed.  It does that when a file is first visited.
> 
> An empty buffer is a fully defined state.  A buffer immediately following
> a deletion is in an undefined state, which requires to know what was
> deleted to make it defined again.

You mean, you cannot just throw away the entire info and recalculate
it anew?  IOW, pretend that you know nothing about this buffer, as if
you have just visited its file?



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 17:15             ` Alan Mackenzie
@ 2016-08-01 19:39               ` Eli Zaretskii
  2016-08-01 20:52                 ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-01 19:39 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Mon, 1 Aug 2016 17:15:52 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> How about the following idea: we create a special purpose undo list
> separate from the existing one.  Every change is recorded on this list,
> regardless of whether or not main undo is disabled.  After each
> invocation of after-change-functions the list is emptied.
> 
>     (defmacro with-change-undone (&rest forms) ...)
> 
> An after-change-function can invoke the macro `with-change-undone' which
> would undo the changes, execute the &rest forms, then redo the changes.
> 
> Surely this would satisfy both of us, no?

Sounds gross, but if this is the only way to solve this problem, and
you can live with it, so can I.

I do suggest to wait with conclusions for a while, perhaps a better
idea will come up.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 19:39               ` Eli Zaretskii
@ 2016-08-01 20:52                 ` Alan Mackenzie
  2016-08-02 14:44                   ` Eli Zaretskii
  2016-08-02 14:46                   ` Stefan Monnier
  0 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-01 20:52 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, emacs-devel

Hello, Eli.

On Mon, Aug 01, 2016 at 10:39:03PM +0300, Eli Zaretskii wrote:
> > Date: Mon, 1 Aug 2016 17:15:52 +0000
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > How about the following idea: we create a special purpose undo list
> > separate from the existing one.  Every change is recorded on this list,
> > regardless of whether or not main undo is disabled.  After each
> > invocation of after-change-functions the list is emptied.

> >     (defmacro with-change-undone (&rest forms) ...)

> > An after-change-function can invoke the macro `with-change-undone' which
> > would undo the changes, execute the &rest forms, then redo the changes.

> > Surely this would satisfy both of us, no?

> Sounds gross, but if this is the only way to solve this problem, and
> you can live with it, so can I.

> I do suggest to wait with conclusions for a while, perhaps a better
> idea will come up.

Slightly less gross, perhaps:
(i) Abandon the use of before-change-functions.
(ii) Enable undo in pre-command-hook, if necessary.
(iii) At each after-change-functions call:
  a - Analyze buffer-undo-list down as far as (or pos (next-nil)), and
    revert the insertion or deletion which as been made, taking
    particular care over coalesced multiple insertions/deletions.
  b - (setq pos (current-position-in-undo-list))
  c - Perform what used to be before-change actions.
  d - restore the insertion/deletion.
  e - Perform the normal after-change functions.
(iv) Disable undo in post-command-hook, if appropriate.

This is less gross in that it uses the standard undo list rather than
creating a new special purpose one.  It would also be usable in existing
Emacsen.  But I still say it would be preferable to have a function
`old-string' callable from after-change-functions rather than having to
mess around with the undo list in (ii), (iii)a, and (iv).

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 16:38 ` Richard Stallman
@ 2016-08-02 10:15   ` Alan Mackenzie
  2016-08-02 10:37     ` Richard Copley
  2016-08-02 14:57     ` Eli Zaretskii
  0 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-02 10:15 UTC (permalink / raw)
  To: Richard Stallman; +Cc: ofv, rcopley, emacs-devel

Hello, Richard.

On Mon, Aug 01, 2016 at 12:38:42PM -0400, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]

>   > There are several functions in .../src/insdel.c which have a parameter
>   > `prepare'.  The meaning of `prepare' is "direct the function to call
>   > prepare_to_modify_buffer" (YUCK!).

> Why do you say "yuck" to that?

Hey, don't misquote me!  I said "YUCK!", not "yuck".  :-)

It's my emotional reaction to a dodgy coding practice.  We have two
functions, one of which assumes far too much about the inner workings of
the other.  This "convolution" (as Richard Copley described it) is
liable to lead to all sorts of tangles and awkwardnesses and things
generally being very difficult to maintain.

> I'm not saying it can't have problems, or that you can't
> think of some change for the better.  However, to merit "yuck",
> it would have to be grossly and conspicuously bad.

I think the particular instance IS grossly and conspicuously bad.  The
resulting code is so difficult to maintain that (i) our
before-change-functions/after-change-functions mechanism is broken, in
that the b-c-f hook is only called for some changes, not all changes;
(ii) Eli Z. has forcefully declined my offer to fix this, on the grounds
that the pertinent code (in .../src/insdel.c) is so fragile that any
attempt to fix it will inevitably introduce hidden bugs elsewhere.

This `prepare' parameter is central to the difficulties of fixing/not
being able to fix the b-c-f/a-c-f mechanism.

> -- 
> Dr Richard Stallman
> President, Free Software Foundation (gnu.org, fsf.org)
> Internet Hall-of-Famer (internethalloffame.org)
> Skype: No way! See stallman.org/skype.html.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 10:15   ` Alan Mackenzie
@ 2016-08-02 10:37     ` Richard Copley
  2016-08-02 16:11       ` Alan Mackenzie
  2016-08-02 14:57     ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Richard Copley @ 2016-08-02 10:37 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Óscar Fuentes, Richard Stallman, Emacs Development

On 2 August 2016 at 11:15, Alan Mackenzie <acm@muc.de> wrote:

> It's my emotional reaction to a dodgy coding practice.  We have two
> functions, one of which assumes far too much about the inner workings of
> the other.  This "convolution" (as Richard Copley described it) is
> liable to lead to all sorts of tangles and awkwardnesses and things
> generally being very difficult to maintain.

:) I think that was Eli.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 16:53           ` Alan Mackenzie
  2016-08-01 17:15             ` Alan Mackenzie
  2016-08-01 19:37             ` Eli Zaretskii
@ 2016-08-02 14:39             ` Stefan Monnier
  2 siblings, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-02 14:39 UTC (permalink / raw)
  To: emacs-devel

> And in such calls, what are the parameters BEG, END, and OLD-LEN supposed
> to mean?

Same as ever: that compared to the last time the hook was run, nothing
was changed before BEG, nothing as changed after END and that the chunk
of text between those two had length OLD-LEN last time the hook was run.

> An empty buffer is a fully defined state.  A buffer immediately following
> a deletion is in an undefined state, which requires to know what was
> deleted to make it defined again.

If you need to know something about the deleted text, you can always
keep track of that info in things like text-properties (or buffer-local
vars).  E.g.:

>> > As a concrete example of this, suppose we have this in a buffer:
>> > 
>> >     #define foo() first line \
>> >                   second line \
>> > 	          third line \
>> > 	          fourth line
>> > 
>> > , and the change consists of deleting the backslash on L2.

You can handle this case with nothing more than an a-c-f and something
like a cc-mode-multiline property applied to the whole CPP construct:
in a-c-f you look at the cc-mode-multiline property at BEG and at END
and you expand the "area to recompute" according to that property.

That's the strategy used by font-lock.

Another strategy is the one used by syntax.el which is to simply
consider everything after BEG as being in need of review (actually,
font-lock also uses this strategy via jit-lock-context).


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 20:52                 ` Alan Mackenzie
@ 2016-08-02 14:44                   ` Eli Zaretskii
  2016-08-02 16:09                     ` Alan Mackenzie
  2016-08-02 14:46                   ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-02 14:44 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Mon, 1 Aug 2016 20:52:23 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> (i) Abandon the use of before-change-functions.
> (ii) Enable undo in pre-command-hook, if necessary.
> (iii) At each after-change-functions call:
>   a - Analyze buffer-undo-list down as far as (or pos (next-nil)), and
>     revert the insertion or deletion which as been made, taking
>     particular care over coalesced multiple insertions/deletions.
>   b - (setq pos (current-position-in-undo-list))
>   c - Perform what used to be before-change actions.
>   d - restore the insertion/deletion.
>   e - Perform the normal after-change functions.
> (iv) Disable undo in post-command-hook, if appropriate.

What I don't get is why do you need to look at the deleted text.  The
after-change-functions called after deletion tells you which buffer
positions were removed, so any data CC Mode holds in its caches about
those positions should be discarded.  Why do you need to actually look
at the removed text itself?  What am I missing?

Regarding the proposal itself, undoing arbitrary changes might be
expensive, both CPU- and memory-wise.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-01 20:52                 ` Alan Mackenzie
  2016-08-02 14:44                   ` Eli Zaretskii
@ 2016-08-02 14:46                   ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-02 14:46 UTC (permalink / raw)
  To: emacs-devel

> Slightly less gross, perhaps:
> (i) Abandon the use of before-change-functions.
> (ii) Enable undo in pre-command-hook, if necessary.
> (iii) At each after-change-functions call:
>   a - Analyze buffer-undo-list down as far as (or pos (next-nil)), and
>     revert the insertion or deletion which as been made, taking
>     particular care over coalesced multiple insertions/deletions.
>   b - (setq pos (current-position-in-undo-list))
>   c - Perform what used to be before-change actions.
>   d - restore the insertion/deletion.
>   e - Perform the normal after-change functions.
> (iv) Disable undo in post-command-hook, if appropriate.

Alan.  I urge you to take a step back and think about how to solve your
problem without looking at the details of each change.

I am 100% sure, based on my experience with lots of major modes
(including cc-mode), that the result will be more robust, simpler, and
at least as efficient.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 10:15   ` Alan Mackenzie
  2016-08-02 10:37     ` Richard Copley
@ 2016-08-02 14:57     ` Eli Zaretskii
  2016-08-02 16:55       ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-02 14:57 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Tue, 2 Aug 2016 10:15:49 +0000
> From: Alan Mackenzie <acm@muc.de>
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> 
> I think the particular instance IS grossly and conspicuously bad.  The
> resulting code is so difficult to maintain that (i) our
> before-change-functions/after-change-functions mechanism is broken, in
> that the b-c-f hook is only called for some changes, not all changes;
> (ii) Eli Z. has forcefully declined my offer to fix this, on the grounds
> that the pertinent code (in .../src/insdel.c) is so fragile that any
> attempt to fix it will inevitably introduce hidden bugs elsewhere.

I'm sorry, but the above doesn't match my views and opinions on this
matter, so I would like to express them as clearly as possible:

 (i)  I disagree that the modification-hooks mechanism is broken.  It
      works as designed; if you read the code, you see that very
      clearly.  (Alan disagrees with the design, but that's another
      matter.)
 (ii) I never said the code which implements the support for these
      hooks is "so fragile that any attempt to fix it will inevitably
      introduce hidden bugs".  The code in insdel.c is rock-solid,
      and I feel confident when I make changes there (as indeed I did
      several times during the last year).  What I fear is not the
      fragility of insdel.c, it's the unintended consequences of
      changing the aspects of it and of its callers that are clearly
      against the original design.  Doing that for introducing some
      important new feature would be justified, but doing that because
      CC Mode made incorrect assumptions about how this mechanism
      works is IMO wrong.

> This `prepare' parameter is central to the difficulties of fixing/not
> being able to fix the b-c-f/a-c-f mechanism.

I don't think the mechanism needs fixing.  The intent of the 'prepare'
parameter is quite clear, and is consistently followed by all the
callers of these functions.

What we need is find the best way of fixing CC Mode based on this or
some other mechanism.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 14:44                   ` Eli Zaretskii
@ 2016-08-02 16:09                     ` Alan Mackenzie
  2016-08-02 16:42                       ` Eli Zaretskii
  2016-08-02 17:24                       ` Stefan Monnier
  0 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-02 16:09 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, emacs-devel

Hello, Eli.

On Tue, Aug 02, 2016 at 05:44:34PM +0300, Eli Zaretskii wrote:
> > Date: Mon, 1 Aug 2016 20:52:23 +0000
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > (i) Abandon the use of before-change-functions.
> > (ii) Enable undo in pre-command-hook, if necessary.
> > (iii) At each after-change-functions call:
> >   a - Analyze buffer-undo-list down as far as (or pos (next-nil)), and
> >     revert the insertion or deletion which as been made, taking
> >     particular care over coalesced multiple insertions/deletions.
> >   b - (setq pos (current-position-in-undo-list))
> >   c - Perform what used to be before-change actions.
> >   d - restore the insertion/deletion.
> >   e - Perform the normal after-change functions.
> > (iv) Disable undo in post-command-hook, if appropriate.

> What I don't get is why do you need to look at the deleted text.  The
> after-change-functions called after deletion tells you which buffer
> positions were removed, so any data CC Mode holds in its caches about
> those positions should be discarded.  Why do you need to actually look
> at the removed text itself?  What am I missing?

Things are cached in text properties on the text itself.  These
properties can only be examined before the text is deleted.

A specific instance of needing to see the deleted text is in the
handling of C++ raw strings.  Such a thing looks like this:

    "foo(<arbitrary characters, including ", \n, "bar) ....>)foo"

.  The "foo" can be any (sensible) sequence of 0-16 characters.  The
contents of the string can be literally anything _except_ the
terminating delimiter ")foo\""; for example it could include both
"\"bar(" and ")bar\"".

Now supposing the buffer is changed by deleting the opening delimiter
"\"foo(".  Lots of text properties in the (formally) raw string need to
be removed.  For example, each "\"" in the raw string has a syntax-table
text property on it to suppress its "string" syntax, and there are text
properties on what used to be the closing delimiter.  For this we need
to know where the string ended, i.e. we need to know the "foo" from the
opening delimiter so that we can search forward for ")foo\"".  This
involves looking at the buffer before it is changed.

> Regarding the proposal itself, undoing arbitrary changes might be
> expensive, both CPU- and memory-wise.

It might.  But what are the alternatives?

Anyhow, most buffer changes are going to be single character insertions
or deletions for which the extra processing time shouldn't be
noticeable.  For something like a large C-w, a little extra time
hopefully won't be too stressfull - undoing that C-w won't involve CC
Mode's syntactic analysis, since all the deleted text properties are
stored in the undo list.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 10:37     ` Richard Copley
@ 2016-08-02 16:11       ` Alan Mackenzie
  0 siblings, 0 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-02 16:11 UTC (permalink / raw)
  To: Richard Copley; +Cc: Óscar Fuentes, Richard Stallman, Emacs Development

Hello, Richard.

On Tue, Aug 02, 2016 at 11:37:09AM +0100, Richard Copley wrote:
> On 2 August 2016 at 11:15, Alan Mackenzie <acm@muc.de> wrote:

> > It's my emotional reaction to a dodgy coding practice.  We have two
> > functions, one of which assumes far too much about the inner workings of
> > the other.  This "convolution" (as Richard Copley described it) is
> > liable to lead to all sorts of tangles and awkwardnesses and things
> > generally being very difficult to maintain.

> :) I think that was Eli.

Actually, it was Noam.  Apologies for my confusion.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 16:09                     ` Alan Mackenzie
@ 2016-08-02 16:42                       ` Eli Zaretskii
  2016-08-02 17:24                       ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-02 16:42 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Tue, 2 Aug 2016 16:09:14 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > What I don't get is why do you need to look at the deleted text.  The
> > after-change-functions called after deletion tells you which buffer
> > positions were removed, so any data CC Mode holds in its caches about
> > those positions should be discarded.  Why do you need to actually look
> > at the removed text itself?  What am I missing?
> 
> Things are cached in text properties on the text itself.  These
> properties can only be examined before the text is deleted.

OK, so you must also have code that computes and places those
properties, right?  What triggers that code?  E.g., when a file is
visited, what invokes that code, and how much of the buffer it
processes when invoked?  If it doesn't process the entire buffer in
one go, how is it invoked to process the rest of the buffer?

> > Regarding the proposal itself, undoing arbitrary changes might be
> > expensive, both CPU- and memory-wise.
> 
> It might.  But what are the alternatives?

I don't know yet.  That's why I asked the questions above.

Thanks.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 14:57     ` Eli Zaretskii
@ 2016-08-02 16:55       ` Alan Mackenzie
  2016-08-02 17:17         ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-02 16:55 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Tue, Aug 02, 2016 at 05:57:18PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 2 Aug 2016 10:15:49 +0000
> > From: Alan Mackenzie <acm@muc.de>
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org

> > I think the particular instance IS grossly and conspicuously bad.  The
> > resulting code is so difficult to maintain that (i) our
> > before-change-functions/after-change-functions mechanism is broken, in
> > that the b-c-f hook is only called for some changes, not all changes;
> > (ii) Eli Z. has forcefully declined my offer to fix this, on the grounds
> > that the pertinent code (in .../src/insdel.c) is so fragile that any
> > attempt to fix it will inevitably introduce hidden bugs elsewhere.

> I'm sorry, but the above doesn't match my views and opinions on this
> matter, so I would like to express them as clearly as possible:

>  (i)  I disagree that the modification-hooks mechanism is broken.  It
>       works as designed; if you read the code, you see that very
>       clearly.  (Alan disagrees with the design, but that's another
>       matter.)

I thought we'd already agreed that no rational design would omit the
before-change-hooks call from an arbitrary subset of changes.  I have
read the code, and what I see is not "works as designed" but "failure
consequently to adhere to the design".  b-c-f is used infrequently
enough that it took CC Mode to expose the failure.

>  (ii) I never said the code which implements the support for these
>       hooks is "so fragile that any attempt to fix it will inevitably
>       introduce hidden bugs".  The code in insdel.c is rock-solid,
>       and I feel confident when I make changes there (as indeed I did
>       several times during the last year).  What I fear is not the
>       fragility of insdel.c, it's the unintended consequences of
>       changing the aspects of it and of its callers that are clearly
>       against the original design.

To me it's perfectly clear the original design was, for each buffer
modification there is exactly one invocation of b-c-f and one of a-c-f.
(That's leaving aside precisely what qualifies as a "buffer
modification" and what doesn't.)

The fact that we're too scared to make the simple changes to adhere to
the design (as documented in the Elisp manual) is precisely what
"fragile code" means.  And "call b-c-f for all changes" should be a
simple change.

>       Doing that for introducing some important new feature would be
>       justified, but doing that because CC Mode made incorrect
>       assumptions about how this mechanism works is IMO wrong.

CC Mode didn't make incorrect assumptions - it followed rigourously the
feature as documented in the Elisp manual.  The implication of your last
paragraph is that before using any core feature, a Lisp hacker should
first examine its implementation to make sure the documentation is
correct.  This is absurd.

Anyhow, it's not just CC Mode.  As already discussed, there are 13 other
files which use before-change-functions, and some of these uses are
going to assume it works as documented, just as CC Mode did.  Sporadic
failures are going to occur in some of these other places, due to those
hook functions sometimes not being called.

> > This `prepare' parameter is central to the difficulties of fixing/not
> > being able to fix the b-c-f/a-c-f mechanism.

> I don't think the mechanism needs fixing.

We'll have to carry on disagreeing about this.  For what it's worth, I
accept that it's not going to get fixed.

> The intent of the 'prepare' parameter is quite clear, and is
> consistently followed by all the callers of these functions.

I don't find the intent clear, since prepare_to_modify_buffer is a
mishmash of miscellaneous things, rather than a "do one thing and do it
well".  

If this `prepare' mechanism hadn't been used, but instead the functions
simply called where they were needed, then adding in the b-c-f calls
could have been trivial.

> What we need is find the best way of fixing CC Mode based on this or
> some other mechanism.

Yes.  CC Mode and the other 13 files.el too.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 16:55       ` Alan Mackenzie
@ 2016-08-02 17:17         ` Eli Zaretskii
  2016-08-02 18:30           ` Eli Zaretskii
  2016-08-02 19:00           ` Unbalanced change hooks (part 2) Alan Mackenzie
  0 siblings, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-02 17:17 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Tue, 2 Aug 2016 16:55:45 +0000
> Cc: rms@gnu.org, ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> >  (i)  I disagree that the modification-hooks mechanism is broken.  It
> >       works as designed; if you read the code, you see that very
> >       clearly.  (Alan disagrees with the design, but that's another
> >       matter.)
> 
> I thought we'd already agreed that no rational design would omit the
> before-change-hooks call from an arbitrary subset of changes.

No, I don't think there was such an agreement.  The set of changes for
which before-change-functions are not called is not arbitrary.

> To me it's perfectly clear the original design was, for each buffer
> modification there is exactly one invocation of b-c-f and one of a-c-f.

If such an original design existed in the distant future, it was long
ago (as in 20 years or more) replaced with what we basically see
today, where every change always triggers a call to
after-change-functions, but only some (the majority, but not all)
trigger the call to before-change-functions.

> (That's leaving aside precisely what qualifies as a "buffer
> modification" and what doesn't.)

I don't think it can be left aside, if you want to understand the
rationale.

> The fact that we're too scared to make the simple changes to adhere to
> the design (as documented in the Elisp manual) is precisely what
> "fragile code" means.  And "call b-c-f for all changes" should be a
> simple change.

We are not scared.  We (I) simply don't want to do that, at least not
yet.  When non-trivial changes were needed in insdel.c, they were done
without fear, including lately by yours truly.

> >       Doing that for introducing some important new feature would be
> >       justified, but doing that because CC Mode made incorrect
> >       assumptions about how this mechanism works is IMO wrong.
> 
> CC Mode didn't make incorrect assumptions - it followed rigourously the
> feature as documented in the Elisp manual.

The ELisp manual doesn't promise that these hooks will be called in
balanced pairs.

> The implication of your last paragraph is that before using any core
> feature, a Lisp hacker should first examine its implementation to
> make sure the documentation is correct.  This is absurd.

No, that's life.  What do you think I did before embarking on writing
the bidirectional display?  A lot of code reading, a lot of
discussions with Gerd Moellmann, more code reading, etc.  All that was
needed even though the display engine has much more detailed overview
comments than almost any other part of Emacs.

> Anyhow, it's not just CC Mode.  As already discussed, there are 13 other
> files which use before-change-functions, and some of these uses are
> going to assume it works as documented, just as CC Mode did.  Sporadic
> failures are going to occur in some of these other places, due to those
> hook functions sometimes not being called.

I will believe that when I see specific bug reports about those other
packages.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 16:09                     ` Alan Mackenzie
  2016-08-02 16:42                       ` Eli Zaretskii
@ 2016-08-02 17:24                       ` Stefan Monnier
  2016-08-07 14:49                         ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-02 17:24 UTC (permalink / raw)
  To: emacs-devel

> Things are cached in text properties on the text itself.

I doubt you only put them on the actual text.

>     "foo(<arbitrary characters, including ", \n, "bar) ....>)foo"

E.g. I doubt you put "foo" on the "foo" text.

> Now supposing the buffer is changed by deleting the opening delimiter
> "\"foo(".  Lots of text properties in the (formally) raw string need to
> be removed.

No, that doesn't have to be the case.  CC-mode does it this way
currently because it decided to add properties on various chars within
that string, but that's not the only choice.  E.g. you could put
a "string fence" property on the first char of the string and refrain
from putting a "string fence" property until the end of the string.
Most other major modes follow this strategy.

> This involves looking at the buffer before it is changed.

Even if you have properties that you need to remove, you don't actually
need to know the text that was there before.  All you need is any
position past the end of the used-to-be-string.  Then you just have to
refresh all properties until that position.  A trivial choice is
point-max but if you want to try and optimize this you can add some
text-property (such as cc-mode-multiline) over the whole string, which
makes it easy to find the end, even when some pats have been deleted.
That's also a common approach in many major modes.

Of course, there are plenty of alternatives if you like to do it
differently.  E.g. you can annotate every Nth char in the buffer with
a text property indicating its "state".  So you won't get the exact end
of the string, but some position slightly past it.  Or you can keep that
information is a side-table holding markers.  Or ...


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 17:17         ` Eli Zaretskii
@ 2016-08-02 18:30           ` Eli Zaretskii
  2016-08-02 19:38             ` Alan Mackenzie
  2016-08-08 14:36             ` Alan Mackenzie
  2016-08-02 19:00           ` Unbalanced change hooks (part 2) Alan Mackenzie
  1 sibling, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-02 18:30 UTC (permalink / raw)
  To: acm; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Tue, 02 Aug 2016 20:17:35 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> 
> > Anyhow, it's not just CC Mode.  As already discussed, there are 13 other
> > files which use before-change-functions, and some of these uses are
> > going to assume it works as documented, just as CC Mode did.  Sporadic
> > failures are going to occur in some of these other places, due to those
> > hook functions sometimes not being called.
> 
> I will believe that when I see specific bug reports about those other
> packages.

Btw, I'm slowly but surely arriving to the conclusion that the
problems we are discussing can only happen when insert-file-contents
is called with VISIT and REPLACE non-nil, i.e. when reverting a
buffer.  Do we have any evidence to the contrary?  If we do, can
someone show or point to such contradicting evidence?

If my conclusion is correct, then we should probably focus on this
particular use case and look for a solution for it, as opposed to
trying to solve some more general problem that seems not to exist.  It
might be much easier and simpler.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 17:17         ` Eli Zaretskii
  2016-08-02 18:30           ` Eli Zaretskii
@ 2016-08-02 19:00           ` Alan Mackenzie
  2016-08-02 19:25             ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-02 19:00 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Tue, Aug 02, 2016 at 08:17:35PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 2 Aug 2016 16:55:45 +0000
> > Cc: rms@gnu.org, ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > >  (i)  I disagree that the modification-hooks mechanism is broken.  It
> > >       works as designed; if you read the code, you see that very
> > >       clearly.  (Alan disagrees with the design, but that's another
> > >       matter.)

> > I thought we'd already agreed that no rational design would omit the
> > before-change-hooks call from an arbitrary subset of changes.

> No, I don't think there was such an agreement.  The set of changes for
> which before-change-functions are not called is not arbitrary.

Would you please characterize these circumstances in a way useful for
people considering the use of before-change-functions.  If you like, I
can then modify Elisp's "Change Hooks" with that information.

> > To me it's perfectly clear the original design was, for each buffer
> > modification there is exactly one invocation of b-c-f and one of a-c-f.

> If such an original design existed in the distant past, it was long
> ago (as in 20 years or more) replaced with what we basically see
> today, where every change always triggers a call to
> after-change-functions, but only some (the majority, but not all)
> trigger the call to before-change-functions.

From the point of view of design, what is the benefit in not calling
b-c-f for that subset of circumstances?

> > (That's leaving aside precisely what qualifies as a "buffer
> > modification" and what doesn't.)

> I don't think it can be left aside, if you want to understand the
> rationale.

I do want to.  Currently, I'm not terribly concerned about exactly
whether some change qualifies as a buffer modification or not.  Just that
when it does, and only half of the change hooks are called, I'd like to
know why.

> > The fact that we're too scared to make the simple changes to adhere to
> > the design (as documented in the Elisp manual) is precisely what
> > "fragile code" means.  And "call b-c-f for all changes" should be a
> > simple change.

> We are not scared.  We (I) simply don't want to do that, at least not
> yet.  When non-trivial changes were needed in insdel.c, they were done
> without fear, including lately by yours truly.

OK.

> > >       Doing that for introducing some important new feature would be
> > >       justified, but doing that because CC Mode made incorrect
> > >       assumptions about how this mechanism works is IMO wrong.

> > CC Mode didn't make incorrect assumptions - it followed rigourously the
> > feature as documented in the Elisp manual.

> The ELisp manual doesn't promise that these hooks will be called in
> balanced pairs.

It does.  before-change-functions is described as:

    .... a list of functions to call before any buffer modification.

after-change-functions is likewise described as:

    .... a list of functions to call after any buffer modification.

.  It may not explicitly say they are paired, but it says each hook is
called after every modification.  This naturally pairs them up.

As a native English speaker, the only alternative interpretation I see
(which is absurd) is that Emacs will call each of these hooks once, after
any buffer modification Emacs choses.  I see no way out of the conclusion
that both of these hooks are to be called after each and every buffer
modification.

> > The implication of your last paragraph is that before using any core
> > feature, a Lisp hacker should first examine its implementation to
> > make sure the documentation is correct.  This is absurd.

> No, that's life.  What do you think I did before embarking on writing
> the bidirectional display?  A lot of code reading, a lot of
> discussions with Gerd Moellmann, more code reading, etc.  All that was
> needed even though the display engine has much more detailed overview
> comments than almost any other part of Emacs.

bidi is a somewhat special case.  Somebody considering the use of the
change hooks should be able to rely on their documentation, without
having to read and understand fileio.c and insdel.c.  

> > Anyhow, it's not just CC Mode.  As already discussed, there are 13 other
> > files which use before-change-functions, and some of these uses are
> > going to assume it works as documented, just as CC Mode did.  Sporadic
> > failures are going to occur in some of these other places, due to those
> > hook functions sometimes not being called.

> I will believe that when I see specific bug reports about those other
> packages.

You won't see them, and neither will I, because they'll be sporadic bugs
with wierd consequences, maybe the odd corrupted buffer once in a blue
moon.  Any that make it to a bug report will end up being closed as not
reproducible.  Other times, something will just fail to work, the user will
gently curse Emacs and try again.  We can just pretend those other files
are OK, I suppose.  A lot of them probably actually will be.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 19:00           ` Unbalanced change hooks (part 2) Alan Mackenzie
@ 2016-08-02 19:25             ` Eli Zaretskii
  2016-08-07 21:16               ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-02 19:25 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Tue, 2 Aug 2016 19:00:24 +0000
> Cc: rms@gnu.org, ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > > I thought we'd already agreed that no rational design would omit the
> > > before-change-hooks call from an arbitrary subset of changes.
> 
> > No, I don't think there was such an agreement.  The set of changes for
> > which before-change-functions are not called is not arbitrary.
> 
> Would you please characterize these circumstances in a way useful for
> people considering the use of before-change-functions.  If you like, I
> can then modify Elisp's "Change Hooks" with that information.

Let's leave this for later, and focus on solving the immediate problem
at hand.

> > If such an original design existed in the distant past, it was long
> > ago (as in 20 years or more) replaced with what we basically see
> > today, where every change always triggers a call to
> > after-change-functions, but only some (the majority, but not all)
> > trigger the call to before-change-functions.
> 
> >From the point of view of design, what is the benefit in not calling
> b-c-f for that subset of circumstances?

I'm not yet 100% sure, but I'm getting there.  In any case, the logic
is very clear, although its rationale I only half-understand for now.

> > The ELisp manual doesn't promise that these hooks will be called in
> > balanced pairs.
> 
> It does.  before-change-functions is described as:
> 
>     .... a list of functions to call before any buffer modification.
> 
> after-change-functions is likewise described as:
> 
>     .... a list of functions to call after any buffer modification.
> 
> .  It may not explicitly say they are paired, but it says each hook is
> called after every modification.  This naturally pairs them up.

Like I said, sticking to such a strict interpretation would cause our
code to be unnecessarily much too complex.  The modification hooks are
supposed to tell you that changes are about to be, or have been, made
in a region, but that doesn't necessarily mean you will have a single
call of before- and after- hook for each of the partial changes.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 18:30           ` Eli Zaretskii
@ 2016-08-02 19:38             ` Alan Mackenzie
  2016-08-03  2:36               ` Eli Zaretskii
  2016-08-08 14:36             ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-02 19:38 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Tue, Aug 02, 2016 at 09:30:37PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 02 Aug 2016 20:17:35 +0300
> > From: Eli Zaretskii <eliz@gnu.org>
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org

> > > Anyhow, it's not just CC Mode.  As already discussed, there are 13 other
> > > files which use before-change-functions, and some of these uses are
> > > going to assume it works as documented, just as CC Mode did.  Sporadic
> > > failures are going to occur in some of these other places, due to those
> > > hook functions sometimes not being called.

> > I will believe that when I see specific bug reports about those other
> > packages.

> Btw, I'm slowly but surely arriving to the conclusion that the
> problems we are discussing can only happen when insert-file-contents
> is called with VISIT and REPLACE non-nil, i.e. when reverting a
> buffer.  Do we have any evidence to the contrary?

As long as C-x C-f on a file changed outside of Emacs is included in
"reverting", then no.

> If we do, can someone show or point to such contradicting evidence?

You haven't said how you reached this conclusion.

I've grepped for calls of the five functions (insert_1_both,
replace_range, del_range_\(1\|byte\|both\)) which have `prepare'
parameters, and noted where the argument is false.  I see 15
occurrences.  They are in callproc.c, coding.c, editfns.c, fileio.c,
fns.c, insdel.c, print.c, and xdisp.c.

Can you persuade me that it wouldn't be a good use of my time to look at
each of these 15 occurrences?  :-)

> If my conclusion is correct, then we should probably focus on this
> particular use case and look for a solution for it, as opposed to
> trying to solve some more general problem that seems not to exist.  It
> might be much easier and simpler.

I hope you're right.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 19:38             ` Alan Mackenzie
@ 2016-08-03  2:36               ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-03  2:36 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Tue, 2 Aug 2016 19:38:35 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > Btw, I'm slowly but surely arriving to the conclusion that the
> > problems we are discussing can only happen when insert-file-contents
> > is called with VISIT and REPLACE non-nil, i.e. when reverting a
> > buffer.  Do we have any evidence to the contrary?
> 
> As long as C-x C-f on a file changed outside of Emacs is included in
> "reverting", then no.

You will see in files.el that C-x C-f on such a file calls
revert-buffer.

> > If we do, can someone show or point to such contradicting evidence?
> 
> You haven't said how you reached this conclusion.

By reading the code, of course.

> I've grepped for calls of the five functions (insert_1_both,
> replace_range, del_range_\(1\|byte\|both\)) which have `prepare'
> parameters, and noted where the argument is false.  I see 15
> occurrences.  They are in callproc.c, coding.c, editfns.c, fileio.c,
> fns.c, insdel.c, print.c, and xdisp.c.
> 
> Can you persuade me that it wouldn't be a good use of my time to look at
> each of these 15 occurrences?  :-)

You can if you want to, of course.  The above is my conclusion from
looking at all those places: the only one that counts is in
insert-file-contents.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 17:24                       ` Stefan Monnier
@ 2016-08-07 14:49                         ` Alan Mackenzie
  2016-08-07 15:09                           ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-07 14:49 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan.

On Tue, Aug 02, 2016 at 01:24:14PM -0400, Stefan Monnier wrote:
> > Things are cached in text properties on the text itself.

> I doubt you only put them on the actual text.

> >     "foo(<arbitrary characters, including ", \n, "bar) ....>)foo"

> E.g. I doubt you put "foo" on the "foo" text.

The text "foo" in "\"foo(" implicitly contains the information "the
matching closing delimiter is at the text ")foo\"" further down the
buffer".

> > Now supposing the buffer is changed by deleting the opening delimiter
> > "\"foo(".  Lots of text properties in the (formally) raw string need to
> > be removed.

> No, that doesn't have to be the case.  CC-mode does it this way
> currently because it decided to add properties on various chars within
> that string, but that's not the only choice.  E.g. you could put
> a "string fence" property on the first char of the string and refrain
> from putting a "string fence" property until the end of the string.
> Most other major modes follow this strategy.

Maybe it could, but that's not the point.  The point here is that after
deleting "\"foo(" (or part of it), the closing delimiter must be found,
even if all that is going to be done is to remove a string fence
property from it.  How will one find this closing delimiter without
knowing that the identifier in it is "foo"?  Indeed, how will one know
to find it without even knowing that a raw string delimiter has been
removed?

> > This involves looking at the buffer before it is changed.

> Even if you have properties that you need to remove, you don't actually
> need to know the text that was there before.

Again, how does one know that a raw string opening delimiter has been
removed?

> All you need is any position past the end of the used-to-be-string.
> Then you just have to refresh all properties until that position.  A
> trivial choice is point-max but if you want to try and optimize this
> you can add some text-property (such as cc-mode-multiline) over the
> whole string, which makes it easy to find the end, even when some pats
> have been deleted.  That's also a common approach in many major modes.

> Of course, there are plenty of alternatives if you like to do it
> differently.  E.g. you can annotate every Nth char in the buffer with
> a text property indicating its "state".  So you won't get the exact end
> of the string, but some position slightly past it.  Or you can keep that
> information is a side-table holding markers.  Or ...

Or one could note the state before a change, and see how the change
changes it.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-07 14:49                         ` Alan Mackenzie
@ 2016-08-07 15:09                           ` Stefan Monnier
  2016-08-07 21:48                             ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-07 15:09 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

> Maybe it could, but that's not the point.  The point here is that after
> deleting "\"foo(" (or part of it), the closing delimiter must be found,
> even if all that is going to be done is to remove a string fence
> property from it.  How will one find this closing delimiter without
> knowing that the identifier in it is "foo"?  Indeed, how will one know
> to find it without even knowing that a raw string delimiter has been
> removed?

Because the text-property on the remaining text says "I'm in the middle
of a raw-string" and it says so until the end of that raw-string, hence
telling you where was the end.

> Or one could note the state before a change, and see how the change
> changes it.

Experience shows that this approach is a lot more complex, especially if
you take into account that before- and after- change-functions calls aren't
guaranteed to come in pairs.

In any case the question was not "can the CC-mode way be made to work"
but "is it the only way".  If it was the only way, it would make sense
to try and support it better.  But it's far from the only way, and
I have enough experience in those matters to even claim that it's far
from being the best way.



        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 19:25             ` Eli Zaretskii
@ 2016-08-07 21:16               ` Alan Mackenzie
  2016-08-08 15:38                 ` Eli Zaretskii
  2016-08-08 19:56                 ` Stefan Monnier
  0 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-07 21:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Tue, Aug 02, 2016 at 10:25:45PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 2 Aug 2016 19:00:24 +0000
> > Cc: rms@gnu.org, ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > > > I thought we'd already agreed that no rational design would omit the
> > > > before-change-hooks call from an arbitrary subset of changes.

> > > No, I don't think there was such an agreement.  The set of changes for
> > > which before-change-functions are not called is not arbitrary.

> > Would you please characterize these circumstances in a way useful for
> > people considering the use of before-change-functions.  If you like, I
> > can then modify Elisp's "Change Hooks" with that information.

> Let's leave this for later, and focus on solving the immediate problem
> at hand.

You say the set of changes for which b-c-f isn't called isn't arbitrary.
That means it follows some sort of scheme.  Could a major mode, in an
after-change function use this scheme to determine whether
before-change-functions was called, for some particular change?  (This
won't be needed if my other idea (below) is workable.)

> > > If such an original design existed in the distant past, it was long
> > > ago (as in 20 years or more) replaced with what we basically see
> > > today, where every change always triggers a call to
> > > after-change-functions, but only some (the majority, but not all)
> > > trigger the call to before-change-functions.

> > >From the point of view of design, what is the benefit in not calling
> > b-c-f for that subset of circumstances?

> I'm not yet 100% sure, but I'm getting there.  In any case, the logic
> is very clear, although its rationale I only half-understand for now.

OK.

> > > The ELisp manual doesn't promise that these hooks will be called in
> > > balanced pairs.

> > It does.  before-change-functions is described as:

> >     .... a list of functions to call before any buffer modification.

> > after-change-functions is likewise described as:

> >     .... a list of functions to call after any buffer modification.

> > .  It may not explicitly say they are paired, but it says each hook is
> > called after every modification.  This naturally pairs them up.

> Like I said, sticking to such a strict interpretation would cause our
> code to be unnecessarily much too complex.  The modification hooks are
> supposed to tell you that changes are about to be, or have been, made
> in a region, but that doesn't necessarily mean you will have a single
> call of before- and after- hook for each of the partial changes.

OK, things are as they are.

I currently believe that most changes trigger before-change-functions but
EVERY CHANGE triggers after-change-functions.  Can you confirm that this
is the case?  If it isn't, could we fix Emacs so that it is?

If it is indeed the case, then a solution to the problem would be to
check that before- and after-c-f are called alternately.  Any time
after-c-f is called twice in a row, we could reverse the change just made
(using the undo list), invoke before-c-f, redo the change, then let
after-c-f continue to completion.  If necessary, we can temporarily
enable undo in a pre-command-hook function.  Given how rarely b-c-f isn't
called, this would have a negligible effect on performance and store
usage.

This would be a better solution than reversing and redoing every change.
It will also work for older Emacsen, and will be relatively easy to
implement.  It will be much easier to implement than a solution which
doesn't use before-change-functions at all.

What do you think about this?

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-07 15:09                           ` Stefan Monnier
@ 2016-08-07 21:48                             ` Alan Mackenzie
  2016-08-08  0:55                               ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-07 21:48 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan.

On Sun, Aug 07, 2016 at 11:09:52AM -0400, Stefan Monnier wrote:
> > Maybe it could, but that's not the point.  The point here is that after
> > deleting "\"foo(" (or part of it), the closing delimiter must be found,
> > even if all that is going to be done is to remove a string fence
> > property from it.  How will one find this closing delimiter without
> > knowing that the identifier in it is "foo"?  Indeed, how will one know
> > to find it without even knowing that a raw string delimiter has been
> > removed?

> Because the text-property on the remaining text says "I'm in the middle
> of a raw-string" and it says so until the end of that raw-string, hence
> telling you where was the end.

OK.  Extrapolating that suggestion, you're suggesting that all the
different types of information about the buffer which are currently
determined in c-before-change should be cached in text properties, or
perhaps in special purpose Lisp structures, and retrieved and used in
c-after-change.

For some types of information this would be easy (such as putting text
properties over C++ raw strings), for others it would be difficult (such
as maintaining the integrity of the c-parse-state cache (yes, _that_
thing)).

> > Or one could note the state before a change, and see how the change
> > changes it.

> Experience shows that this approach is a lot more complex, especially if
> you take into account that before- and after- change-functions calls aren't
> guaranteed to come in pairs.

I now have an idea (see my recent post to Eli) to _make_ these hook
calls properly paired.  This should be reliable and easy to implement.

You seem to be arguing that using all the information about a change is
more complicated than ignoring some of it.  I can't see how that can be
the case.  If one is missing part of the information, it is surely going
to be rather complicated to work around that lack.

> In any case the question was not "can the CC-mode way be made to work"
> but "is it the only way".  If it was the only way, it would make sense
> to try and support it better.  But it's far from the only way, and
> I have enough experience in those matters to even claim that it's far
> from being the best way.

"It's far from the only way" is what I have been saying for some while
about your way of handling, for example, syntax-table text properties.

Have you ever tried doing things the "CC Mode way", i.e. using
information from before-change-functions in an essential fashion?  If
so, please tell me about it, and what it was that brought you to giving
up on it.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-07 21:48                             ` Alan Mackenzie
@ 2016-08-08  0:55                               ` Stefan Monnier
  0 siblings, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-08  0:55 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

> For some types of information this would be easy (such as putting text
> properties over C++ raw strings), for others it would be difficult (such
> as maintaining the integrity of the c-parse-state cache (yes, _that_
> thing)).

For this one, you don't need to know what changed either.  You just
restart from some point before BEG and compare the resulting state at
some point after END (after potentially adjusting the old state's
positions based on LENGTH).

> I now have an idea (see my recent post to Eli) to _make_ these hook
> calls properly paired.  This should be reliable and easy to implement.

I personally can't see any way you can make them properly paired in 100%
of the cases (including the case where one of the hooks itself makes
a buffer modification, for example).

> You seem to be arguing that using all the information about a change is
> more complicated than ignoring some of it.

Oh, yes.  And my attempt at using syntax-propertize in CC-mode comforts
me in this belief (even tho, I obviously only did the easy part).

> I can't see how that can be the case.  If one is missing part of the
> information, it is surely going to be rather complicated to work
> around that lack.

As Eli pointed out several times already, your code *has* to handle the
case where you have no prior knowledge, because that's what happens when
you open the file (or when you insert a new chunk of text).

So actually trying to use the information about "what was there before"
is extra effort.

> Have you ever tried doing things the "CC Mode way", i.e. using
> information from before-change-functions in an essential fashion?

No, because I know it's based on an invalid assumption.

> If so, please tell me about it, and what it was that brought you to
> giving up on it.

But as mentioned above, I've since had a look at what it takes to go
from "the CC-mode way" to "the usual way", and it mostly involves
removing (somewhat duplicate) code.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-02 18:30           ` Eli Zaretskii
  2016-08-02 19:38             ` Alan Mackenzie
@ 2016-08-08 14:36             ` Alan Mackenzie
  2016-08-08 15:42               ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-08 14:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Tue, Aug 02, 2016 at 09:30:37PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 02 Aug 2016 20:17:35 +0300
> > From: Eli Zaretskii <eliz@gnu.org>
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org

> > > Anyhow, it's not just CC Mode.  As already discussed, there are 13 other
> > > files which use before-change-functions, and some of these uses are
> > > going to assume it works as documented, just as CC Mode did.  Sporadic
> > > failures are going to occur in some of these other places, due to those
> > > hook functions sometimes not being called.
 
> > I will believe that when I see specific bug reports about those other
> > packages.

> Btw, I'm slowly but surely arriving to the conclusion that the
> problems we are discussing can only happen when insert-file-contents
> is called with VISIT and REPLACE non-nil, i.e. when reverting a
> buffer.  Do we have any evidence to the contrary?  If we do, can
> someone show or point to such contradicting evidence?

> If my conclusion is correct, then we should probably focus on this
> particular use case and look for a solution for it, as opposed to
> trying to solve some more general problem that seems not to exist.  It
> might be much easier and simpler.

Using buffer-undo-list temporarily to reverse a change and run
c-before-change seems to work well when the undo list is enabled.  When
it isn't enabled, I run into problems which don't look like being solved
easily.

If you're right in supposing that only insert-file-contents with those
particular parameters can cause the omission of the
before-change-functions call, then a solution would be for CC Mode to
advise those commands which call insert-f-c this way.  That advice would
cause the command to test and clear a flag set by CC Mode, and if it was
non-nil, to repeat the command.

Repeating find-file and revert-buffer in these circumstances appears to
work.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-07 21:16               ` Alan Mackenzie
@ 2016-08-08 15:38                 ` Eli Zaretskii
  2016-08-08 19:56                 ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-08 15:38 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Sun, 7 Aug 2016 21:16:27 +0000
> Cc: rms@gnu.org, ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> You say the set of changes for which b-c-f isn't called isn't arbitrary.
> That means it follows some sort of scheme.  Could a major mode, in an
> after-change function use this scheme to determine whether
> before-change-functions was called, for some particular change?

Not easily, not without some bookkeeping.

> I currently believe that most changes trigger before-change-functions but
> EVERY CHANGE triggers after-change-functions.  Can you confirm that this
> is the case?

Yes.

> If it is indeed the case, then a solution to the problem would be to
> check that before- and after-c-f are called alternately.  Any time
> after-c-f is called twice in a row, we could reverse the change just made
> (using the undo list), invoke before-c-f, redo the change, then let
> after-c-f continue to completion.  If necessary, we can temporarily
> enable undo in a pre-command-hook function.  Given how rarely b-c-f isn't
> called, this would have a negligible effect on performance and store
> usage.
> 
> This would be a better solution than reversing and redoing every change.
> It will also work for older Emacsen, and will be relatively easy to
> implement.  It will be much easier to implement than a solution which
> doesn't use before-change-functions at all.
> 
> What do you think about this?

I'm extremely uneasy about using undo for such purposes.  You have
already discovered one reason why.  In general, applications are free
to manipulate the undo records as they see fit, so you cannot expect
that to work reliably.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-08 14:36             ` Alan Mackenzie
@ 2016-08-08 15:42               ` Eli Zaretskii
  2016-08-08 16:54                 ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-08 15:42 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Mon, 8 Aug 2016 14:36:14 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> If you're right in supposing that only insert-file-contents with those
> particular parameters can cause the omission of the
> before-change-functions call, then a solution would be for CC Mode to
> advise those commands which call insert-f-c this way.

I thought our policy was to leave advising to users, and never do
that in core.

I asked a few questions a couple of days ago, with the purpose of
coming up with idea for how to solve this issue in a more acceptable
way.  You never answered them.  Could you please humor me?

If nothing better comes up, I'd prefer to do something special in
insert-file-contents, specifically for CC Mode, rather than going to
the extremes you describe above and in the other messages.

Thanks.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-08 15:42               ` Eli Zaretskii
@ 2016-08-08 16:54                 ` Alan Mackenzie
  2016-08-08 17:17                   ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-08 16:54 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Mon, Aug 08, 2016 at 06:42:20PM +0300, Eli Zaretskii wrote:
> > Date: Mon, 8 Aug 2016 14:36:14 +0000
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > If you're right in supposing that only insert-file-contents with those
> > particular parameters can cause the omission of the
> > before-change-functions call, then a solution would be for CC Mode to
> > advise those commands which call insert-f-c this way.

> I thought our policy was to leave advising to users, and never do
> that in core.

I suppose so.  In that case, I can do the advising in standalone CC
Mode, but we hard code a solution in savannah master.

> I asked a few questions a couple of days ago, with the purpose of
> coming up with idea for how to solve this issue in a more acceptable
> way.  You never answered them.  Could you please humor me?

Sorry about that.  I think you mean the following.  Otherwise, would you
please clarify.

#########################################################################

>> Things are cached in text properties on the text itself.  These
>> properties can only be examined before the text is deleted.

> OK, so you must also have code that computes and places those
> properties, right?

Yes.

> What triggers that code?

before/after-change-functions.  For example, in C++ Mode, if a "<"
template delimiter is about is in a region about to be deleted, and the
matching ">" is after that region, the pertinent function called from
c-before-change (c-before-change-check-<>-operators) removes the
syntax-table properties from each of them.

> E.g., when a file is visited, what invokes that code, and how much of
> the buffer it processes when invoked?

On a newly visited file, the entire buffer is scanned by (the components
of) c-before-change and c-after-change, setting the text properties.

> If it doesn't process the entire buffer in one go, how is it invoked
> to process the rest of the buffer?

It does process the entire buffer in one go.

#########################################################################

> If nothing better comes up, I'd prefer to do something special in
> insert-file-contents, specifically for CC Mode, rather than going to
> the extremes you describe above and in the other messages.

What I'm looking at at the moment is calling revert-buffer a second time
if CC Mode signals a missing before-change-functions the first time.
After the test scenario, M-x revert-buffer works, so it might work if
called from the code instead.

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-08 16:54                 ` Alan Mackenzie
@ 2016-08-08 17:17                   ` Eli Zaretskii
  2016-08-08 18:42                     ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-08 17:17 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Mon, 8 Aug 2016 16:54:49 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > What triggers that code?
> 
> before/after-change-functions.  For example, in C++ Mode, if a "<"
> template delimiter is about is in a region about to be deleted, and the
> matching ">" is after that region, the pertinent function called from
> c-before-change (c-before-change-check-<>-operators) removes the
> syntax-table properties from each of them.
> 
> > E.g., when a file is visited, what invokes that code, and how much of
> > the buffer it processes when invoked?
> 
> On a newly visited file, the entire buffer is scanned by (the components
> of) c-before-change and c-after-change, setting the text properties.

So, if worse comes to worst, you could trigger such a complete scan
after revert-buffer, e.g. in a specialized revert-buffer-function.

Do you have a way of completely forgetting everything about a certain
region of buffer text, and rescanning that region anew?  If so, would
it work to do this in c-after-change, since its arguments tell you
both the old and the new buffer positions where the changes were made?
If this works, it might be less expensive then rescanning the entire
buffer.

> What I'm looking at at the moment is calling revert-buffer a second time
> if CC Mode signals a missing before-change-functions the first time.
> After the test scenario, M-x revert-buffer works, so it might work if
> called from the code instead.

I don't understand how this could work reliably: it has the same
problems as the original recipe.  Am I missing something?



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-08 17:17                   ` Eli Zaretskii
@ 2016-08-08 18:42                     ` Alan Mackenzie
  2016-08-08 19:04                       ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-08 18:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Mon, Aug 08, 2016 at 08:17:42PM +0300, Eli Zaretskii wrote:
> > Date: Mon, 8 Aug 2016 16:54:49 +0000
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > > What triggers that code?

> > before/after-change-functions.  For example, in C++ Mode, if a "<"
> > template delimiter is about is in a region about to be deleted, and the
> > matching ">" is after that region, the pertinent function called from
> > c-before-change (c-before-change-check-<>-operators) removes the
> > syntax-table properties from each of them.

> > > E.g., when a file is visited, what invokes that code, and how much of
> > > the buffer it processes when invoked?

> > On a newly visited file, the entire buffer is scanned by (the components
> > of) c-before-change and c-after-change, setting the text properties.

> So, if worse comes to worst, you could trigger such a complete scan
> after revert-buffer, e.g. in a specialized revert-buffer-function.

Why would that be bad?  We detect the bad condition by two consecutive
after-c-f calls, check that revert-buffer is on the call stack, and
twiddle `beg' `end' `old-len' (the parameters to after-change functions)
to indicate the entire buffer.  Then let c-after-change carry on.  This
feels too easy.  :-)  What am I missing?

> Do you have a way of completely forgetting everything about a certain
> region of buffer text, and rescanning that region anew?

This is tricky, because, for example, template delimiters outside that
region are associated with deleted (or unmarked) delimiters inside the
region.

> If so, would it work to do this in c-after-change, since its arguments
> tell you both the old and the new buffer positions where the changes
> were made?  If this works, it might be less expensive then rescanning
> the entire buffer.

I don't think this would work.  beg, end, and old-len only say where
things were changed, not what syntax-table'd characters have been
deleted.  Anyway, what's so bad about scanning the entire buffer after
having reverted it?

> > What I'm looking at at the moment is calling revert-buffer a second time
> > if CC Mode signals a missing before-change-functions the first time.
> > After the test scenario, M-x revert-buffer works, so it might work if
> > called from the code instead.

> I don't understand how this could work reliably: it has the same
> problems as the original recipe.  Am I missing something?

There is nothing like buffer-undo-list which can be corrupted by other
programs.  Anyhow, I've implemented it, and it works well on the test
case from bug #24094.  Here is the embryonic patch (I haven't reindented
code, so as to keep the patch short, and there's message output).  It
works, for the moment, by putting "around" advice around revert-buffer,
and invoking ad-do-it a second time if the first time didn't work:




diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 04d2ed6..4db71b6 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -492,10 +492,13 @@ c-maybe-stale-found-type
 (defvar c-just-done-before-change nil)
 (make-variable-buffer-local 'c-just-done-before-change)
 ;; This variable is set to t by `c-before-change' and to nil by
-;; `c-after-change'.  It is used to detect a spurious invocation of
-;; `before-change-functions' directly following on from a correct one.  This
-;; happens in some Emacsen, for example when `basic-save-buffer' does (insert
-;; ?\n) when `require-final-newline' is non-nil.
+;; `c-after-change'.  It is used for two purposes: (i) to detect a spurious
+;; invocation of `before-change-functions' directly following on from a
+;; correct one.  This happens in some Emacsen, for example when
+;; `basic-save-buffer' does (insert ?\n) when `require-final-newline' is
+;; non-nil; (ii) to detect when Emacs fails to invoke
+;; `before-change-functions'.  This can happend when reverting a buffer - see
+;; bug #24094.
 
 (defun c-basic-common-init (mode default-style)
   "Do the necessary initialization for the syntax handling routines
@@ -643,8 +646,9 @@ c-basic-common-init
   (add-hook 'after-change-functions 'c-after-change nil t)
   (when (boundp 'font-lock-extend-after-change-region-function)
     (set (make-local-variable 'font-lock-extend-after-change-region-function)
-         'c-extend-after-change-region))) ; Currently (2009-05) used by all
+         'c-extend-after-change-region)) ; Currently (2009-05) used by all
                           ; languages with #define (C, C++,; ObjC), and by AWK.
+  (add-hook 'pre-command-hook 'c-pre-command-hook t))
 
 (defun c-setup-doc-comment-style ()
   "Initialize the variables that depend on the value of `c-doc-comment-style'."
@@ -1225,6 +1229,22 @@ c-before-change
     ;; newly inserted parens would foul up the invalidation algorithm.
     (c-invalidate-state-cache beg)))
 
+(defvar c-missed-before-change nil)
+
+(defun c-pre-command-hook ()
+  (setq c-missed-before-change nil))
+
+(defadvice revert-buffer (around c-advise-revert-buffer activate)
+  ad-do-it
+  (when (and c-buffer-is-cc-mode
+	     c-missed-before-change)
+    (message "Repeating revert-buffer.")
+    (setq c-missed-before-change nil)
+    ad-do-it
+    (message "Repeated revert-buffer %s"
+	     (if c-missed-before-change "failed" "succeeded"))
+    ))
+
 (defvar c-in-after-change-fontification nil)
 (make-variable-buffer-local 'c-in-after-change-fontification)
 ;; A flag to prevent region expanding stuff being done twice for after-change
@@ -1244,6 +1264,10 @@ c-after-change
   ;; This calls the language variable c-before-font-lock-functions, if non nil.
   ;; This typically sets `syntax-table' properties.
 
+  ;; Rarely, Emacs will fail to call `before-change-functions'.  See bug
+  ;; #24094.  In such cases, do it "by hand".
+  (if (not c-just-done-before-change)
+      (setq c-missed-before-change t)
   ;; (c-new-BEG c-new-END) will be the region to fontify.  It may become
   ;; larger than (beg end).
   (setq c-new-END (- (+ c-new-END (- end beg)) old-len))
@@ -1291,7 +1315,7 @@ c-after-change
 	  (save-excursion
 	    (mapc (lambda (fn)
 		    (funcall fn beg end old-len))
-		  c-before-font-lock-functions)))))))
+		  c-before-font-lock-functions))))))))
 
 (defun c-fl-decl-start (pos)
   ;; If the beginning of the line containing POS is in the middle of a "local"
@@ -1483,6 +1507,8 @@ c-extend-after-change-region
   ;; Of the seven CC Mode languages, currently (2009-05) only C, C++, Objc
   ;; (the languages with #define) and AWK Mode make non-null use of this
   ;; function.
+  (if c-missed-before-change
+      (cons beg end)
   (when (eq font-lock-support-mode 'jit-lock-mode)
     (save-restriction
       (widen)
@@ -1491,7 +1517,7 @@ c-extend-after-change-region
 	    (put-text-property c-new-BEG beg 'fontified nil))
 	(if (> c-new-END end)
 	    (put-text-property end c-new-END 'fontified nil)))))
-  (cons c-new-BEG c-new-END))
+  (cons c-new-BEG c-new-END)))
 
 ;; Emacs < 22 and XEmacs
 (defmacro c-advise-fl-for-region (function)


-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply related	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-08 18:42                     ` Alan Mackenzie
@ 2016-08-08 19:04                       ` Eli Zaretskii
  2016-08-08 19:54                         ` Unbalanced change hooks (part 2) [PATCH] Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-08 19:04 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Mon, 8 Aug 2016 18:42:23 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > So, if worse comes to worst, you could trigger such a complete scan
> > after revert-buffer, e.g. in a specialized revert-buffer-function.
> 
> Why would that be bad?

Not bad, just potentially expensive for large buffers.  But if that's
"good enough", I don't really mind.

However, the patch you show below doesn't implement this, does it?



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [PATCH]
  2016-08-08 19:04                       ` Eli Zaretskii
@ 2016-08-08 19:54                         ` Alan Mackenzie
  2016-08-09 15:08                           ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-08 19:54 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Mon, Aug 08, 2016 at 10:04:45PM +0300, Eli Zaretskii wrote:
> > Date: Mon, 8 Aug 2016 18:42:23 +0000
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > > So, if worse comes to worst, you could trigger such a complete scan
> > > after revert-buffer, e.g. in a specialized revert-buffer-function.

> > Why would that be bad?

> Not bad, just potentially expensive for large buffers.  But if that's
> "good enough", I don't really mind.

> However, the patch you show below doesn't implement this, does it?

No, but the following does.  It looks kind of simple, given the problems
we've been through.  Maybe this one is the solution:



diff -r 7a969360b796 cc-mode.el
--- a/cc-mode.el	Fri Aug 05 08:13:50 2016 +0000
+++ b/cc-mode.el	Mon Aug 08 19:46:40 2016 +0000
@@ -475,10 +475,13 @@
 (defvar c-just-done-before-change nil)
 (make-variable-buffer-local 'c-just-done-before-change)
 ;; This variable is set to t by `c-before-change' and to nil by
-;; `c-after-change'.  It is used to detect a spurious invocation of
-;; `before-change-functions' directly following on from a correct one.  This
-;; happens in some Emacsen, for example when `basic-save-buffer' does (insert
-;; ?\n) when `require-final-newline' is non-nil.
+;; `c-after-change'.  It is used for two purposes: (i) to detect a spurious
+;; invocation of `before-change-functions' directly following on from a
+;; correct one.  This happens in some Emacsen, for example when
+;; `basic-save-buffer' does (insert ?\n) when `require-final-newline' is
+;; non-nil; (ii) to detect when Emacs fails to invoke
+;; `before-change-functions'.  This can happend when reverting a buffer - see
+;; bug #24094.
 
 (defun c-basic-common-init (mode default-style)
   "Do the necessary initialization for the syntax handling routines
@@ -1220,6 +1223,18 @@
   ;; This calls the language variable c-before-font-lock-functions, if non nil.
   ;; This typically sets `syntax-table' properties.
 
+  ;; We can sometimes get two consecutive calls to `after-change-functions'
+  ;; without an intervening call to `before-change-functions' when reverting
+  ;; the buffer (see bug #24094).  Whatever the cause assume that the entire
+  ;; buffer has changed.
+  (when (not c-just-done-before-change)
+    (save-restriction
+      (widen)
+      (c-before-change (point-min) (point-max))
+      (setq beg (point-min)
+	    end (point-max)
+	    old-len (- end beg))))
+
   ;; (c-new-BEG c-new-END) will be the region to fontify.  It may become
   ;; larger than (beg end).
   (setq c-new-END (- (+ c-new-END (- end beg)) old-len))


-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-07 21:16               ` Alan Mackenzie
  2016-08-08 15:38                 ` Eli Zaretskii
@ 2016-08-08 19:56                 ` Stefan Monnier
  2016-08-08 20:16                   ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-08 19:56 UTC (permalink / raw)
  To: emacs-devel

> If it is indeed the case, then a solution to the problem would be to
> check that before- and after-c-f are called alternately.  Any time
> after-c-f is called twice in a row, we could reverse the change just made
> (using the undo list), invoke before-c-f, redo the change, then let
> after-c-f continue to completion.  If necessary, we can temporarily

Sounds like piling up workarounds to make up for a mistake in the
underlying design.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-08 19:56                 ` Stefan Monnier
@ 2016-08-08 20:16                   ` Alan Mackenzie
  0 siblings, 0 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-08 20:16 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan

On Mon, Aug 08, 2016 at 03:56:24PM -0400, Stefan Monnier wrote:
> > If it is indeed the case, then a solution to the problem would be to
> > check that before- and after-c-f are called alternately.  Any time
> > after-c-f is called twice in a row, we could reverse the change just made
> > (using the undo list), invoke before-c-f, redo the change, then let
> > after-c-f continue to completion.  If necessary, we can temporarily

> Sounds like piling up workarounds to make up for a mistake in the
> underlying design.

I couldn't agree more!

Anyway, we've now got what is surely a satisfactory solution: in the
event of a missing call to before-change-functions, assume that the
entirety of the buffer has changed (which is not far from the truth,
given that it happens on a `revert-buffer') and run
c-{before,after}-change on this basis.  See the patch in my latest post
to Eli.

This switches off some of the optimisations intended for revert-buffer,
but these seem no longer quite so pressing, given that reverting
xdisp.c, even with my latest patch, takes less than 0.2s on my 7 y.o.
machine; 20 years ago, things would have been different.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 15:03 ` Eli Zaretskii
  2016-07-31 17:28   ` Alan Mackenzie
@ 2016-08-09 15:01   ` Alan Mackenzie
  2016-08-09 15:14     ` Eli Zaretskii
  2016-08-19 14:51   ` Phillip Lord
  2 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-09 15:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, emacs-devel

Hello, Eli.

On Sun, Jul 31, 2016 at 06:03:19PM +0300, Eli Zaretskii wrote:
> > Date: Sun, 31 Jul 2016 12:16:42 +0000
> > From: Alan Mackenzie <acm@muc.de>
> > Cc: Óscar Fuentes <ofv@wanadoo.es>,
> > 	Richard Copley <rcopley@gmail.com>

> > I propose that the call to signal_before_change should be removed from
> > prepare_to_modify_buffer, and that it should be called explicitly from
> > the places it is needed.  This would allow bug #240[79]4 to be fixed.

> > Comments?

> Some.

> First, I don't agree with your conclusion that calls to
> before-change-functions and after-change-functions must always be
> balanced.  For starters, they aren't, and never have been.

I don't think this is true.  A data point is that in XEmacs's insdel.c
(which is quite a bit simpler than Emacs's) the calls to b-c-f and a-c-f
are balanced.  Bug #24049 doesn't trigger on XEmacs.  I think it's
likely this balance existed in Emacs until some time after the Lucid
Emacs fork.

My guess is that originally these hooks were _intended_ to be balanced
(as they still are, at least to a very great extent, on XEmacs).  At
some stage (probably in the late 1990s/early 2000s) optimisations were
made in insdel.c and elsewhere, and the strict pairing of b-c-f and
a-c-f got lost in the wash.  At that time, very little, if anything,
used b-c-f, hence there was nothing to signal alarm bells during the
testing of the optimisations.

As I said, that's my guess.  I've tried searching the emacs-devel
archive for early discussions on the topic, but not found anything.

[ .... ]

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [PATCH]
  2016-08-08 19:54                         ` Unbalanced change hooks (part 2) [PATCH] Alan Mackenzie
@ 2016-08-09 15:08                           ` Eli Zaretskii
  2016-08-09 16:38                             ` Unbalanced change hooks (part 2) [Documentation fix still remaining] Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-09 15:08 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Mon, 8 Aug 2016 19:54:59 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> Hello, Eli.
> 
> On Mon, Aug 08, 2016 at 10:04:45PM +0300, Eli Zaretskii wrote:
> > > Date: Mon, 8 Aug 2016 18:42:23 +0000
> > > Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> > > From: Alan Mackenzie <acm@muc.de>
> 
> > > > So, if worse comes to worst, you could trigger such a complete scan
> > > > after revert-buffer, e.g. in a specialized revert-buffer-function.
> 
> > > Why would that be bad?
> 
> > Not bad, just potentially expensive for large buffers.  But if that's
> > "good enough", I don't really mind.
> 
> > However, the patch you show below doesn't implement this, does it?
> 
> No, but the following does.  It looks kind of simple, given the problems
> we've been through.  Maybe this one is the solution:

LGTM, thanks.  Feel free to install, and close this issue.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-09 15:01   ` Alan Mackenzie
@ 2016-08-09 15:14     ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-09 15:14 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, emacs-devel

> Date: Tue, 9 Aug 2016 15:01:32 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> My guess is that originally these hooks were _intended_ to be balanced
> (as they still are, at least to a very great extent, on XEmacs).  At
> some stage (probably in the late 1990s/early 2000s) optimisations were
> made in insdel.c and elsewhere, and the strict pairing of b-c-f and
> a-c-f got lost in the wash.

No, the 'prepare' argument was added in 1994 (Emacs 19.2x), and
starting from that change, the hooks were never balanced.  You can
clearly see that in the Git history output.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-09 15:08                           ` Eli Zaretskii
@ 2016-08-09 16:38                             ` Alan Mackenzie
  2016-08-09 16:42                               ` Eli Zaretskii
  2016-08-09 17:14                               ` Stefan Monnier
  0 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-09 16:38 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Tue, Aug 09, 2016 at 06:08:14PM +0300, Eli Zaretskii wrote:
> > Date: Mon, 8 Aug 2016 19:54:59 +0000
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

[ .... ]

> > > However, the patch you show below doesn't implement this, does it?

> > No, but the following does.  It looks kind of simple, given the problems
> > we've been through.  Maybe this one is the solution:

> LGTM, thanks.  Feel free to install, and close this issue.

DONE.

However there's still the inaccuracy in the Elisp documentation for
before-change-functions.  In particular there's the bit in "Change Hooks"
that says:

    This variable holds a list of functions to call before _ANY_ buffer
    modification.

, which is grossly misleading, at best.

Should I open another bug report for this, or are you just going to be
fixing it anyway (or giving me the info so that I can fix it)?

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-09 16:38                             ` Unbalanced change hooks (part 2) [Documentation fix still remaining] Alan Mackenzie
@ 2016-08-09 16:42                               ` Eli Zaretskii
  2016-08-09 18:13                                 ` Eli Zaretskii
  2016-08-09 17:14                               ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-09 16:42 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: ofv, rcopley, rms, emacs-devel

> Date: Tue, 9 Aug 2016 16:38:14 +0000
> Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > > No, but the following does.  It looks kind of simple, given the problems
> > > we've been through.  Maybe this one is the solution:
> 
> > LGTM, thanks.  Feel free to install, and close this issue.
> 
> DONE.

Thanks.

> However there's still the inaccuracy in the Elisp documentation for
> before-change-functions.  In particular there's the bit in "Change Hooks"
> that says:
> 
>     This variable holds a list of functions to call before _ANY_ buffer
>     modification.
> 
> , which is grossly misleading, at best.
> 
> Should I open another bug report for this, or are you just going to be
> fixing it anyway (or giving me the info so that I can fix it)?

I will fix it.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-09 16:38                             ` Unbalanced change hooks (part 2) [Documentation fix still remaining] Alan Mackenzie
  2016-08-09 16:42                               ` Eli Zaretskii
@ 2016-08-09 17:14                               ` Stefan Monnier
  2016-08-09 18:19                                 ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-09 17:14 UTC (permalink / raw)
  To: emacs-devel

>     This variable holds a list of functions to call before _ANY_ buffer
>     modification.

I think this description is correct.  If there's a modification where we
forget to run the hook, please report it as a bug.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-09 16:42                               ` Eli Zaretskii
@ 2016-08-09 18:13                                 ` Eli Zaretskii
  2016-08-09 18:35                                   ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-09 18:13 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, acm, rms, rcopley, emacs-devel

> Date: Tue, 09 Aug 2016 19:42:23 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org
> 
> > However there's still the inaccuracy in the Elisp documentation for
> > before-change-functions.  In particular there's the bit in "Change Hooks"
> > that says:
> > 
> >     This variable holds a list of functions to call before _ANY_ buffer
> >     modification.
> > 
> > , which is grossly misleading, at best.
> > 
> > Should I open another bug report for this, or are you just going to be
> > fixing it anyway (or giving me the info so that I can fix it)?
> 
> I will fix it.

Done (on the emacs-25 branch).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-09 17:14                               ` Stefan Monnier
@ 2016-08-09 18:19                                 ` Eli Zaretskii
  2016-08-09 19:09                                   ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-09 18:19 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Tue, 09 Aug 2016 13:14:56 -0400
> 
> >     This variable holds a list of functions to call before _ANY_ buffer
> >     modification.
> 
> I think this description is correct.  If there's a modification where we
> forget to run the hook, please report it as a bug.

I think this is just an argument about the definition of
"modification".  When a modification is done piecemeal, not every
partial modification calls the before hook.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-09 18:13                                 ` Eli Zaretskii
@ 2016-08-09 18:35                                   ` Alan Mackenzie
  0 siblings, 0 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-09 18:35 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, rcopley, rms, emacs-devel

Hello, Eli.

On Tue, Aug 09, 2016 at 09:13:43PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 09 Aug 2016 19:42:23 +0300
> > From: Eli Zaretskii <eliz@gnu.org>
> > Cc: ofv@wanadoo.es, rcopley@gmail.com, rms@gnu.org, emacs-devel@gnu.org

> > > However there's still the inaccuracy in the Elisp documentation for
> > > before-change-functions.  In particular there's the bit in "Change Hooks"
> > > that says:

> > >     This variable holds a list of functions to call before _ANY_ buffer
> > >     modification.

> > > , which is grossly misleading, at best.

> > > Should I open another bug report for this, or are you just going to be
> > > fixing it anyway (or giving me the info so that I can fix it)?

> > I will fix it.

> Done (on the emacs-25 branch).

You've changed "any" to "most", which although technically not incorrect,
is lacking in usefulness.  In particular, it gives a user of
before-change-functions no way to predict which modifications will call
it and which ones won't.

I think "most" is a bit misleading - it suggests a proportion of,
perhaps, 60% - 90%, whereas I think the figure in real usage is well over
99%.  "Almost all", I think, would be a better description than "most",
but still inadequate.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-09 18:19                                 ` Eli Zaretskii
@ 2016-08-09 19:09                                   ` Stefan Monnier
  2016-08-10 14:21                                     ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-09 19:09 UTC (permalink / raw)
  To: emacs-devel

>> >     This variable holds a list of functions to call before _ANY_ buffer
>> >     modification.
>> I think this description is correct.  If there's a modification where we
>> forget to run the hook, please report it as a bug.
> I think this is just an argument about the definition of
> "modification".  When a modification is done piecemeal, not every
> partial modification calls the before hook.

It's OK if we call it once for the whole region and then modify various
chunks of the region one by one, yes.  In that case, it's still called
before those modification.

Basically, It think we should guarantee that if buffer position N is
changed, then N is between the BEG and END of the latest call to b-c-f
(with END potentially adjusted to account for the other modifications
that took place in the mean time).


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-09 19:09                                   ` Stefan Monnier
@ 2016-08-10 14:21                                     ` Eli Zaretskii
  2016-08-10 14:56                                       ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-10 14:21 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Tue, 09 Aug 2016 15:09:02 -0400
> 
> It's OK if we call it once for the whole region and then modify various
> chunks of the region one by one, yes.  In that case, it's still called
> before those modification.
> 
> Basically, It think we should guarantee that if buffer position N is
> changed, then N is between the BEG and END of the latest call to b-c-f
> (with END potentially adjusted to account for the other modifications
> that took place in the mean time).

AFAICT, this is what happens, indeed, except that the call to
before-change-functions in some cases does not precede the first
modification of the series.  IOW, by the time the hook is called, some
modifications were already done.




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 14:21                                     ` Eli Zaretskii
@ 2016-08-10 14:56                                       ` Stefan Monnier
  2016-08-10 15:16                                         ` Alan Mackenzie
  2016-08-10 16:03                                         ` Eli Zaretskii
  0 siblings, 2 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-10 14:56 UTC (permalink / raw)
  To: emacs-devel

> AFAICT, this is what happens, indeed,

Then the old text was right: it's called before ANY modification.

> except that the call to before-change-functions in some cases does not
> precede the first modification of the series.  IOW, by the time the
> hook is called, some modifications were already done.

Sounds like a bug.

In any case, my point is that the doc should still say "before any
modification" because that's really what the code *should* do.  We could
add a blurb in the doc saying that the before and after hooks may not be
properly paired (neither in number of calls nor in the specific value of
BEG/END), but we should still claim that they're both called for any and
all modifications (modulo inhibit-modification-hooks, obviously).


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 14:56                                       ` Stefan Monnier
@ 2016-08-10 15:16                                         ` Alan Mackenzie
  2016-08-10 15:44                                           ` Stefan Monnier
  2016-08-10 16:03                                         ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-10 15:16 UTC (permalink / raw)
  To: Stefan Monnier, Eli Zaretskii; +Cc: emacs-devel

Hello, Stefan and Eli.

On Wed, Aug 10, 2016 at 10:56:59AM -0400, Stefan Monnier wrote:
> > AFAICT, this is what happens, indeed,

> Then the old text was right: it's called before ANY modification.

> > except that the call to before-change-functions in some cases does not
> > precede the first modification of the series.  IOW, by the time the
> > hook is called, some modifications were already done.

> Sounds like a bug.

I concur.

> In any case, my point is that the doc should still say "before any
> modification" because that's really what the code *should* do.  We could
> add a blurb in the doc saying that the before and after hooks may not be
> properly paired (neither in number of calls nor in the specific value of
> BEG/END),

You mean we should add commentary saying that BEG and END _usually_
bound the region about to be deleted, but sometimes they don't.  And
another comment saying that BEG, END, and OLD-LEN are only _usually_ set
to what they're currently documented as, the rest of the time they're
random numbers vaguely related to a change region.

That doesn't sound much better to me.

If we're going to treat the code (as opposed to the documentation) as a
bug, let's fix it completely, with rigorously paired b-c-f and a-c-f,
rather than half-heartedly.

Otherwise, let's document fully the circumstances in which
before-change-functions doesn't get called (which I don't as yet
understand), so that Lisp hackers can use that information in their
programs.

> but we should still claim that they're both called for any and
> all modifications (modulo inhibit-modification-hooks, obviously).

Given that the situation has been in place for several decades, I don't
see any urgency to fix it in 25.1.  But let's fix it properly, whatever
we decide the bug is.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 15:16                                         ` Alan Mackenzie
@ 2016-08-10 15:44                                           ` Stefan Monnier
  0 siblings, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-10 15:44 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Eli Zaretskii, emacs-devel

>> In any case, my point is that the doc should still say "before any
>> modification" because that's really what the code *should* do.  We could
>> add a blurb in the doc saying that the before and after hooks may not be
>> properly paired (neither in number of calls nor in the specific value of
>> BEG/END),
> You mean we should add commentary saying that BEG and END _usually_
> bound the region about to be deleted, but sometimes they don't.

No.  They should always bound the region.  But sometimes the before and
after bounds are different (typically, they're tighter in a-c-f because
when the b-c-f is run we don't know yet exactly which parts will be
modified, so we give pessimistic bounds).

E.g. I think it would be perfectly acceptable to have a revert-buffer
with b-c-f called once on point-min/point-max and then a-c-f called
a bunch of times on those few places where the buffer actually needed to
be modified.

>> but we should still claim that they're both called for any and
>> all modifications (modulo inhibit-modification-hooks, obviously).
> Given that the situation has been in place for several decades, I don't
> see any urgency to fix it in 25.1.

Agreed.  But the doc should still say what the "spec" should be, so it's
clear what is a bug.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 14:56                                       ` Stefan Monnier
  2016-08-10 15:16                                         ` Alan Mackenzie
@ 2016-08-10 16:03                                         ` Eli Zaretskii
  2016-08-10 16:11                                           ` Stefan Monnier
  2016-08-10 16:18                                           ` Alan Mackenzie
  1 sibling, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-10 16:03 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Wed, 10 Aug 2016 10:56:59 -0400
> 
> > AFAICT, this is what happens, indeed,
> 
> Then the old text was right: it's called before ANY modification.

Convince Alan, and I will change it back.

> > except that the call to before-change-functions in some cases does not
> > precede the first modification of the series.  IOW, by the time the
> > hook is called, some modifications were already done.
> 
> Sounds like a bug.

I'm not convinced it's a bug.

> In any case, my point is that the doc should still say "before any
> modification" because that's really what the code *should* do.  We could
> add a blurb in the doc saying that the before and after hooks may not be
> properly paired (neither in number of calls nor in the specific value of
> BEG/END), but we should still claim that they're both called for any and
> all modifications

Which is inaccurate when modifications are done in several separate
parts, and you already agreed it's okay to call the hooks only once.
So "for any and all modifications" is bound to draw fire from people
who take that at face value.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 16:03                                         ` Eli Zaretskii
@ 2016-08-10 16:11                                           ` Stefan Monnier
  2016-08-18 14:26                                             ` Eli Zaretskii
  2016-08-10 16:18                                           ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-10 16:11 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

>> > AFAICT, this is what happens, indeed,
>> Then the old text was right: it's called before ANY modification.
> Convince Alan, and I will change it back.
>> > except that the call to before-change-functions in some cases does not
>> > precede the first modification of the series.  IOW, by the time the
>> > hook is called, some modifications were already done.
>> Sounds like a bug.
> I'm not convinced it's a bug.

before-change-functions should be called *before* a
change occurs.  If there is a call to b-c-f before the first
modification, and then another call before the second modification in
that series, then it's OK (assuming the BEG/END values are sufficiently
large in each call to cover the changes that occur before the next call).

But if a change occurs without having been "announced" by an earlier
b-c-f then it's a bug.

>> In any case, my point is that the doc should still say "before any
>> modification" because that's really what the code *should* do.  We could
>> add a blurb in the doc saying that the before and after hooks may not be
>> properly paired (neither in number of calls nor in the specific value of
>> BEG/END), but we should still claim that they're both called for any and
>> all modifications
> Which is inaccurate when modifications are done in several separate
> parts, and you already agreed it's okay to call the hooks only once.
> So "for any and all modifications" is bound to draw fire from people
> who take that at face value.

They're free to misunderstand it, I'm fine with it.  But saying it's
called for "most" implies that there are changes where b-c-f is simply
not called at all, which would break uses such as syntax-ppss's.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 16:03                                         ` Eli Zaretskii
  2016-08-10 16:11                                           ` Stefan Monnier
@ 2016-08-10 16:18                                           ` Alan Mackenzie
  2016-08-10 16:54                                             ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-10 16:18 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Stefan Monnier, emacs-devel

Hello, Eli.

On Wed, Aug 10, 2016 at 07:03:04PM +0300, Eli Zaretskii wrote:
> > From: Stefan Monnier <monnier@iro.umontreal.ca>
> > Date: Wed, 10 Aug 2016 10:56:59 -0400

> > > AFAICT, this is what happens, indeed,
 
> > Then the old text was right: it's called before ANY modification.

> Convince Alan, and I will change it back.

For what it's worth, I don't like the vagueness of the doc as it
currently is, and I wouldn't be against changing it back _FOR 25.1_
We've got a bug, but it's not urgent enough to have to be fixed for
25.1.

> > > except that the call to before-change-functions in some cases does not
> > > precede the first modification of the series.  IOW, by the time the
> > > hook is called, some modifications were already done.

> > Sounds like a bug.

> I'm not convinced it's a bug.

> > In any case, my point is that the doc should still say "before any
> > modification" because that's really what the code *should* do.  We could
> > add a blurb in the doc saying that the before and after hooks may not be
> > properly paired (neither in number of calls nor in the specific value of
> > BEG/END), but we should still claim that they're both called for any and
> > all modifications

> Which is inaccurate when modifications are done in several separate
> parts, and you already agreed it's okay to call the hooks only once.
> So "for any and all modifications" is bound to draw fire from people
> who take that at face value.

Some while ago, I think you said that there is a systematic basis for
when before-change-functions doesn't get called.  Is that still your
view?  If so, let's document that system.  If not, then let's fix the
code so that it is systematic.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 16:18                                           ` Alan Mackenzie
@ 2016-08-10 16:54                                             ` Eli Zaretskii
  2016-08-10 17:49                                               ` Alan Mackenzie
  2016-08-10 18:57                                               ` Alan Mackenzie
  0 siblings, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-10 16:54 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: monnier, emacs-devel

> Date: Wed, 10 Aug 2016 16:18:21 +0000
> Cc: Stefan Monnier <monnier@iro.umontreal.ca>, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > > Then the old text was right: it's called before ANY modification.
> 
> > Convince Alan, and I will change it back.
> 
> For what it's worth, I don't like the vagueness of the doc as it
> currently is, and I wouldn't be against changing it back _FOR 25.1_
> We've got a bug, but it's not urgent enough to have to be fixed for
> 25.1.

I made further adjustments to the text.  It is now closer to what it
was before, but I don't feel it's wise for it to be as definitive as
it was originally, as someone will surely interpret that too literally
and file another bug report, or design a feature based on incorrect
assumptions.

> Some while ago, I think you said that there is a systematic basis for
> when before-change-functions doesn't get called.  Is that still your
> view?

Yes.

> If so, let's document that system.

It's too complicated to describe that.  We would need to describe some
internal aspects of the implementation in great detail.  I don't see
that as worth our while.

Thanks.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 16:54                                             ` Eli Zaretskii
@ 2016-08-10 17:49                                               ` Alan Mackenzie
  2016-08-10 18:10                                                 ` Eli Zaretskii
  2016-08-10 18:57                                               ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-10 17:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel

Hello, Eli.

On Wed, Aug 10, 2016 at 07:54:36PM +0300, Eli Zaretskii wrote:
> > Date: Wed, 10 Aug 2016 16:18:21 +0000
> > Cc: Stefan Monnier <monnier@iro.umontreal.ca>, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > > > Then the old text was right: it's called before ANY modification.

[ .... ]

> > Some while ago, I think you said that there is a systematic basis for
> > when before-change-functions doesn't get called.  Is that still your
> > view?

> Yes.

> > If so, let's document that system.

> It's too complicated to describe that.  We would need to describe some
> internal aspects of the implementation in great detail.  I don't see
> that as worth our while.

I can't see the difference between your last paragraph and saying it's
totally arbitrary.  If the only way to categorise it is to say "look at
the source code" that's arbitrary.

It can not be a good thing for the call to before-change-functions to be
missed out arbitrarily.

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 17:49                                               ` Alan Mackenzie
@ 2016-08-10 18:10                                                 ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-10 18:10 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: monnier, emacs-devel

> Date: Wed, 10 Aug 2016 17:49:30 +0000
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > It's too complicated to describe that.  We would need to describe some
> > internal aspects of the implementation in great detail.  I don't see
> > that as worth our while.
> 
> I can't see the difference between your last paragraph and saying it's
> totally arbitrary.  If the only way to categorise it is to say "look at
> the source code" that's arbitrary.
> 
> It can not be a good thing for the call to before-change-functions to be
> missed out arbitrarily.

It's not arbitrary.  But describing when we don't call the
before-change hooks would first need to describe the various parts of
some buffer modifications, because otherwise you'd be unable to
understand which part does and which doesn't call them.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 16:54                                             ` Eli Zaretskii
  2016-08-10 17:49                                               ` Alan Mackenzie
@ 2016-08-10 18:57                                               ` Alan Mackenzie
  2016-08-10 19:08                                                 ` Eli Zaretskii
  2016-08-10 19:50                                                 ` Stefan Monnier
  1 sibling, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-10 18:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel

Hello, Eli.

On Wed, Aug 10, 2016 at 07:54:36PM +0300, Eli Zaretskii wrote:
> > Date: Wed, 10 Aug 2016 16:18:21 +0000
> > Cc: Stefan Monnier <monnier@iro.umontreal.ca>, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > > > Then the old text was right: it's called before ANY modification.

> > > Convince Alan, and I will change it back.

> > For what it's worth, I don't like the vagueness of the doc as it
> > currently is, and I wouldn't be against changing it back _FOR 25.1_
> > We've got a bug, but it's not urgent enough to have to be fixed for
> > 25.1.

> I made further adjustments to the text.  It is now closer to what it
> was before, but I don't feel it's wise for it to be as definitive as
> it was originally, as someone will surely interpret that too literally
> and file another bug report, or design a feature based on incorrect
> assumptions.

#########################################################################

  Do @emph{not} expect the before-change hooks and the after-change
  hooks be called in balanced pairs around each buffer change.  Also
  don't expect the before-change hooks to be called for every chunk of
  text Emacs is about to delete.  These hooks are provided on the
  assumption that Lisp programs will use either before- or the
  after-change hooks, but not both, and the boundaries of the region
  where the changes happen might include more than just the actual
  changed text, or even lump together several changes done piecemeal.

#########################################################################

I don't like that text at all.  For what it's worth, I find it
objectionable in the extreme.  It's not even true.  One can (indeed,
often MUST) expect b-c-f and a-c-f to work in pairs, and it is only on
the rarest of occasions that they do not - it's taken ~10 years for this
bug to show up.

Editing text involves deletions and insertions.  Deletions can be known
only in before-change-functions, insertions only in
after-change-functions.  What you are proposing is partitioning Elisp
programs into those that know only deletions, and those that know only
insertions.  Any program using syntax-ppss would by that principle be
debarred from using a-c-f, since s-ppss uses b-c-f.  This is absurd.

If you insist on this strand of documentation (which is surely
controversial enough not to be allowed into Emacs 25.1 at this late
stage) then please provide a function called something like `old-text'
which an after-change function could use to recover deleted text.

CC Mode absolutely requires to know both deletions and insertions for
its proper functioning.  Nobody has yet demonstrated that it can work
properly knowing only insertions, despite Stefan loudly and repeatedly
proclaiming it can.

Must I look forward to a bug report from some busybody moaning that CC
Mode "illegitimately" uses both change hooks?

OK, I've complained enough, so I ought to suggest something positive.
Here is what I would put into the documentation in place of that
paragraph.  I think it is accurate and reasonable.

#########################################################################

  Normally the before-change-functions and the after-change-functions
  hooks are called in balanced pairs around each buffer change, enabling
  state to be determined in a before-change function and used in an
  after-change function.  However on rare occasions,
  before-change-functions is not called before a buffer change and
  after-change-functions is thus called twice in succession.  Your
  program should be ready to deal with such an occurrence.

#########################################################################

[ .... ]

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 18:57                                               ` Alan Mackenzie
@ 2016-08-10 19:08                                                 ` Eli Zaretskii
  2016-08-10 19:50                                                 ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-10 19:08 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: monnier, emacs-devel

> Date: Wed, 10 Aug 2016 18:57:35 +0000
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> #########################################################################
> 
>   Do @emph{not} expect the before-change hooks and the after-change
>   hooks be called in balanced pairs around each buffer change.  Also
>   don't expect the before-change hooks to be called for every chunk of
>   text Emacs is about to delete.  These hooks are provided on the
>   assumption that Lisp programs will use either before- or the
>   after-change hooks, but not both, and the boundaries of the region
>   where the changes happen might include more than just the actual
>   changed text, or even lump together several changes done piecemeal.
> 
> #########################################################################
> 
> I don't like that text at all.  For what it's worth, I find it
> objectionable in the extreme.  It's not even true.

OK, I'm now officially done with discussing this with you.  I find
your ingratitude and downright rudeness extremely out of line.  I
regret I ever started talking about this.

This text stays.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 18:57                                               ` Alan Mackenzie
  2016-08-10 19:08                                                 ` Eli Zaretskii
@ 2016-08-10 19:50                                                 ` Stefan Monnier
  2016-08-11 11:29                                                   ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-10 19:50 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Eli Zaretskii, emacs-devel

>   Do @emph{not} expect the before-change hooks and the after-change
>   hooks be called in balanced pairs around each buffer change.  Also
>   don't expect the before-change hooks to be called for every chunk of
>   text Emacs is about to delete.  These hooks are provided on the
>   assumption that Lisp programs will use either before- or the
>   after-change hooks, but not both, and the boundaries of the region
>   where the changes happen might include more than just the actual
>   changed text, or even lump together several changes done piecemeal.

That looks OK, thank you.  It does make it sound like sometimes b-c-f
won't be called at all, whereas AFAIU it is *always* called before
a change, tho maybe "too early" (i.e. announcing several changes at the
same time), but I think it's good enough for now.

> One can (indeed, often MUST) expect b-c-f and a-c-f to work in pairs,

No.  I know you *want* to expect it, but that assumption has not been
true for many years and we don't want to impose it on ourselves.
Furthermore there is no evidence that you "MUST".
I gave various examples of ways you can live with only a-c-f.

> Editing text involves deletions and insertions.

It also involves replacements.

> Deletions can be known only in before-change-functions, insertions
> only in after-change-functions.

Not at all.  Deletions are definitely announced to a-c-f.

> CC Mode absolutely requires to know both deletions and insertions for
> its proper functioning.  Nobody has yet demonstrated that it can work
> properly knowing only insertions, despite Stefan loudly and repeatedly
> proclaiming it can.

All major modes using syntax-propertize demonstrate it.  C++ has its
share of syntactic quirks, but none that are fundamentally very
different from what we find in other languages such as Perl.

I also outlined in more detailed how to deal with a specific example you
seemed to think required absolutely to know what was there before
the deletion.

>   enabling state to be determined in a before-change function and used
>   in an after-change function.

That's exactly what I want to strongly discourage.  Based on my
experience with CC-mode, I'd even say that it's just a bad design, even
if the hooks were always called in pairs.  I don't know nor care about
how we ended up with such a design, and I understand that you might
prefer to try and live with it than to go back and rethink it, but it's
still a bad design (nor is it the only bad design we have in Emacs, of
course).


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 19:50                                                 ` Stefan Monnier
@ 2016-08-11 11:29                                                   ` Alan Mackenzie
  2016-08-11 16:43                                                     ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-11 11:29 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan.

On Wed, Aug 10, 2016 at 03:50:06PM -0400, Stefan Monnier wrote:
> >   Do @emph{not} expect the before-change hooks and the after-change
> >   hooks be called in balanced pairs around each buffer change.  Also
> >   don't expect the before-change hooks to be called for every chunk of
> >   text Emacs is about to delete.  These hooks are provided on the
> >   assumption that Lisp programs will use either before- or the
> >   after-change hooks, but not both, and the boundaries of the region
> >   where the changes happen might include more than just the actual
> >   changed text, or even lump together several changes done piecemeal.

> That looks OK, thank you.  It does make it sound like sometimes b-c-f
> won't be called at all,

That is the current status, yes.  In the bug which gave rise to this
discussion, bug #24094, a certain change did not call b-c-f at all.

> whereas AFAIU it is *always* called before a change, tho maybe "too
> early" (i.e. announcing several changes at the same time), but I think
> it's good enough for now.

> > One can (indeed, often MUST) expect b-c-f and a-c-f to work in pairs,

> No.  I know you *want* to expect it, but that assumption has not been
> true for many years and we don't want to impose it on ourselves.

The Elisp manual, up until yesterday, documented implicitly that b-c-f
and a-c-f were paired.  It has also been true, up to 99.99..%, otherwise
CC Mode wouldn't work at all.

> Furthermore there is no evidence that you "MUST".
> I gave various examples of ways you can live with only a-c-f.

Vague hand-waving is what I remember.

> > Editing text involves deletions and insertions.

> It also involves replacements.

> > Deletions can be known only in before-change-functions, insertions
> > only in after-change-functions.

> Not at all.  Deletions are definitely announced to a-c-f.

You know full well what I mean.  By the time you get to a-c-f the
deletion as announced is a hollowed out husk, all its details except for
its position and size having been lost.

What you and Eli are asserting is that one NEVER IN ANY CIRCUMSTANCES
needs to know the full details of a buffer modification, and no program
now or in the future ever will.  The burden of proof has not been met.
With the recent change in documentation, Emacs 25.1 has become a less
powerful programming system, one in which these details cannot be
determined.

> > CC Mode absolutely requires to know both deletions and insertions for
> > its proper functioning.  Nobody has yet demonstrated that it can work
> > properly knowing only insertions, despite Stefan loudly and repeatedly
> > proclaiming it can.

> All major modes using syntax-propertize demonstrate it.  C++ has its
> share of syntactic quirks, but none that are fundamentally very
> different from what we find in other languages such as Perl.

If you want to try and construct a CC Mode which disregards deletions,
you are welcome.  I won't stand in your way.  But I will try and break
it.

[ .... ]

> >   enabling state to be determined in a before-change function and used
> >   in an after-change function.

> That's exactly what I want to strongly discourage.  Based on my
> experience with CC-mode, I'd even say that it's just a bad design, even
> if the hooks were always called in pairs.  I don't know nor care about
> how we ended up with such a design, ....

You really ought to: those who are ignorant of history are doomed to
repeat it.

> .... and I understand that you might prefer to try and live with it
> than to go back and rethink it, but it's still a bad design (nor is it
> the only bad design we have in Emacs, of course).

You've been libelling my design for longer than I can remember.  It's
different from how you'd try to do it, that's all.  It's a good design,
and it works well.  It's a straightforward and obvious distillation of
requirements and Emacs's documented features.  You recently admitted
you'd never tried to build anything that way, so you're just saying "my
way is better".

As I say, if you really think your way is better, hack it, and we can
compare.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-11 11:29                                                   ` Alan Mackenzie
@ 2016-08-11 16:43                                                     ` Stefan Monnier
  2016-08-28 11:23                                                       ` Daniel Colascione
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-11 16:43 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

> That is the current status, yes.  In the bug which gave rise to this
> discussion, bug #24094, a certain change did not call b-c-f at all.

Right, but that's a bug, not a misfeature we want to document.

> The Elisp manual, up until yesterday, documented implicitly that b-c-f
> and a-c-f were paired.

No: you read it as documenting this implicitly, but that's a misunderstanding.

>> Furthermore there is no evidence that you "MUST".
>> I gave various examples of ways you can live with only a-c-f.
> Vague hand-waving is what I remember.

That's because you don't want to think about it seriously: Of course
it's not in the form of a patch to CC-mode that passes all your tests
plus various performance assessments, no.  But those "vague hand-waving"
refer to techniques used in actual code in various major modes facing
similar problems.

> You know full well what I mean.  By the time you get to a-c-f the
> deletion as announced is a hollowed out husk, all its details except for
> its position and size having been lost.

As mentioned in my so-called "hand-waving", any details you may need can
be stored somewhere for use.

But there's no reason your code could *require* this data for correct
behavior, since your code also has to handle the more general case where
all the text after BEG has been replaced by something else which may or
may not include similar contents and may or may not already include some
text-properties like `syntax-table'.

> What you and Eli are asserting is that one NEVER IN ANY CIRCUMSTANCES
> needs to know the full details of a buffer modification, and no program
> now or in the future ever will.

Exactly.  And that's because the code has to handle the previously
mentioned general case anyway.

> With the recent change in documentation, Emacs 25.1 has become a less
> powerful programming system, one in which these details cannot
> be determined.

Nope.  The documentation is just more honest than before.

> If you want to try and construct a CC Mode which disregards deletions,
> you are welcome.  I won't stand in your way.  But I will try and break it.

I expect no less.

>> .... and I understand that you might prefer to try and live with it
>> than to go back and rethink it, but it's still a bad design (nor is it
>> the only bad design we have in Emacs, of course).
> You've been libelling my design for longer than I can remember.
> It's different from how you'd try to do it, that's all.

No, that's not all.  It's based on an invalid assumption about b-c-f and
a-c-f, and even if that assumption was true I contend that it leads to
more complex code.

It probably has some performance advantages in some cases, of course.
By I doubt it has a performance advantage "on average".

> It's a straightforward and obvious distillation of requirements and
> Emacs's documented features.

No idea what you mean by that.

> You recently admitted you'd never tried to build anything that way, so
> you're just saying "my way is better".

I also tried to replace in CC-mode "your way" with mine and found mine
to be simpler.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-10 16:11                                           ` Stefan Monnier
@ 2016-08-18 14:26                                             ` Eli Zaretskii
  2016-08-18 16:56                                               ` Stefan Monnier
  2016-08-19  8:45                                               ` Alan Mackenzie
  0 siblings, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-18 14:26 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: emacs-devel@gnu.org
> Date: Wed, 10 Aug 2016 12:11:21 -0400
> 
> >> > except that the call to before-change-functions in some cases does not
> >> > precede the first modification of the series.  IOW, by the time the
> >> > hook is called, some modifications were already done.
> >> Sounds like a bug.
> > I'm not convinced it's a bug.
> 
> before-change-functions should be called *before* a
> change occurs.  If there is a call to b-c-f before the first
> modification, and then another call before the second modification in
> that series, then it's OK (assuming the BEG/END values are sufficiently
> large in each call to cover the changes that occur before the next call).
> 
> But if a change occurs without having been "announced" by an earlier
> b-c-f then it's a bug.

I've reviewed all the places where we may not call the before- and the
after-change hooks.  They are just a few.

One questionable place is insert-file-contents: it deliberately never
calls the before-change-functions when it deletes portions of the
text, only when it inserts text.  I don't really understand the
reasons behind your insisting on before-change-functions being called
before any changes in this case, but maybe a simple way out would be
to announce at the beginning of the function that the entire range
between point-min and point-max is about to be changed, when REPLACE
is non-nil.

Another place where before-change-functions is not called, but
after-change-functions are is set-buffer-multibyte.  Moreover, if the
function is called with a nil argument, we don't call
after-change-functions as well.  Is that supposed to be handled as a
buffer change or not?

In the low levels of encoding and decoding routines, we sometimes call
the hooks and sometimes don't, depending on what is the source and the
destination of the en/decoding, and whether there are pre-write or
pre-write conversions.  But the buffer in question is a temporary
conversion buffer, so do we care?

In message_dolog, which is called by any code which logs a message in
*Messages*, we never call the before-change-functions for the
*Messages* buffer, but we do call the after-change-functions for it.
Problem or not?

That's all I found.

> >> In any case, my point is that the doc should still say "before any
> >> modification" because that's really what the code *should* do.  We could
> >> add a blurb in the doc saying that the before and after hooks may not be
> >> properly paired (neither in number of calls nor in the specific value of
> >> BEG/END), but we should still claim that they're both called for any and
> >> all modifications
> > Which is inaccurate when modifications are done in several separate
> > parts, and you already agreed it's okay to call the hooks only once.
> > So "for any and all modifications" is bound to draw fire from people
> > who take that at face value.
> 
> They're free to misunderstand it, I'm fine with it.

Then what is the value of such a misleading documentation?

The current text says:

  This variable holds a list of functions to call when Emacs is about
  to modify a buffer.

It intentionally refrains from saying "any and all modifications", and
instead tries to be more vague.  Do you still think this is not good
enough?  Because if you do, I don't see how we can say anything more
accurate and yet avoid misleading the reader.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-18 14:26                                             ` Eli Zaretskii
@ 2016-08-18 16:56                                               ` Stefan Monnier
  2016-08-19  8:45                                               ` Alan Mackenzie
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-18 16:56 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

> One questionable place is insert-file-contents: it deliberately never
> calls the before-change-functions when it deletes portions of the
> text, only when it inserts text.

So, if insert-file-contents only deletes a portion of text, it doesn't
call before-change-functions at all?  That'd be a bug, yes.

> I don't really understand the reasons behind your insisting on
> before-change-functions being called before any changes in this case,

For example, because syntax-ppss uses before-change-functions to notice
when the cache needs to be flushed, and that is necessary for any
change, including deletions, and whether the deletion is performed by 
insert-file-contents or something else is mostly irrelevant.

> but maybe a simple way out would be to announce at the beginning of
> the function that the entire range between point-min and point-max is
> about to be changed, when REPLACE is non-nil.

That'd be pessimistic, but yes, it's an easy way to fix the bug, and
it'd probably be good enough.

> Another place where before-change-functions is not called, but
> after-change-functions are is set-buffer-multibyte.  Moreover, if the
> function is called with a nil argument, we don't call
> after-change-functions as well.  Is that supposed to be handled as a
> buffer change or not?

Good question.  I guess it would make sense to call b-c-f on the
whole buffer.  This said, I think we should strongly discourage use of
set-buffer-multibyte in non-empty buffers, so it's not terribly
important: in the "normal" case set-buffer-multibyte should not perform
any buffer modification anyway.

> In the low levels of encoding and decoding routines, we sometimes call
> the hooks and sometimes don't, depending on what is the source and the
> destination of the en/decoding, and whether there are pre-write or
> pre-write conversions.  But the buffer in question is a temporary
> conversion buffer, so do we care?

The temp-conversion-buffer is an internal implementation detail.
I'd rather we never call a/b-c-f in those, but it's not terribly important.

> In message_dolog, which is called by any code which logs a message in
> *Messages*, we never call the before-change-functions for the
> *Messages* buffer, but we do call the after-change-functions for it.
> Problem or not?

The *Messages* buffer is sufficiently special that I'm not worried.

> That's all I found.

Great, thank you very much.

> It intentionally refrains from saying "any and all modifications", and
> instead tries to be more vague.  Do you still think this is not good
> enough?

I think it's good enough.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-18 14:26                                             ` Eli Zaretskii
  2016-08-18 16:56                                               ` Stefan Monnier
@ 2016-08-19  8:45                                               ` Alan Mackenzie
  2016-08-19  9:12                                                 ` Eli Zaretskii
  2016-08-19  9:19                                                 ` Stefan Monnier
  1 sibling, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-19  8:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Stefan Monnier, emacs-devel

Hello, Eli.

On Thu, Aug 18, 2016 at 05:26:03PM +0300, Eli Zaretskii wrote:
> > From: Stefan Monnier <monnier@iro.umontreal.ca>
> > Cc: emacs-devel@gnu.org
> > Date: Wed, 10 Aug 2016 12:11:21 -0400

> > >> > except that the call to before-change-functions in some cases does not
> > >> > precede the first modification of the series.  IOW, by the time the
> > >> > hook is called, some modifications were already done.
> > >> Sounds like a bug.
> > > I'm not convinced it's a bug.

> > before-change-functions should be called *before* a
> > change occurs.  If there is a call to b-c-f before the first
> > modification, and then another call before the second modification in
> > that series, then it's OK (assuming the BEG/END values are sufficiently
> > large in each call to cover the changes that occur before the next call).

> > But if a change occurs without having been "announced" by an earlier
> > b-c-f then it's a bug.

> I've reviewed all the places where we may not call the before- and the
> after-change hooks.  They are just a few.

Thanks!

> One questionable place is insert-file-contents: it deliberately never
> calls the before-change-functions when it deletes portions of the
> text, only when it inserts text.  I don't really understand the
> reasons behind your insisting on before-change-functions being called
> before any changes in this case, but maybe a simple way out would be
> to announce at the beginning of the function that the entire range
> between point-min and point-max is about to be changed, when REPLACE
> is non-nil.

That might create difficulties for CC Mode.  CC Mode now recognises when
b-c-f isn't called at all, but isn't, as far as I've thought it through,
prepared to deal with b-c-f with inaccurate arguments.

> Another place where before-change-functions is not called, but
> after-change-functions are is set-buffer-multibyte.  Moreover, if the
> function is called with a nil argument, we don't call
> after-change-functions as well.  Is that supposed to be handled as a
> buffer change or not?

Possibly not - only the lowest levels of code would notice any
difference.

> In the low levels of encoding and decoding routines, we sometimes call
> the hooks and sometimes don't, depending on what is the source and the
> destination of the en/decoding, and whether there are pre-write or
> pre-write conversions.  But the buffer in question is a temporary
> conversion buffer, so do we care?

> In message_dolog, which is called by any code which logs a message in
> *Messages*, we never call the before-change-functions for the
> *Messages* buffer, but we do call the after-change-functions for it.
> Problem or not?

"Change Hooks" in the Elisp manual states that b-c-f and a-c-f are not
called for the *Messages* buffer.  So I would say calling a-c-f here is a
bug.

> That's all I found.

> > >> In any case, my point is that the doc should still say "before any
> > >> modification" because that's really what the code *should* do.  We could
> > >> add a blurb in the doc saying that the before and after hooks may not be
> > >> properly paired (neither in number of calls nor in the specific value of
> > >> BEG/END), but we should still claim that they're both called for any and
> > >> all modifications
> > > Which is inaccurate when modifications are done in several separate
> > > parts, and you already agreed it's okay to call the hooks only once.
> > > So "for any and all modifications" is bound to draw fire from people
> > > who take that at face value.

> > They're free to misunderstand it, I'm fine with it.

> Then what is the value of such a misleading documentation?

> The current text says:

>   This variable holds a list of functions to call when Emacs is about
>   to modify a buffer.

Somebody wanting to use b-c-f and reading that text is likely to conclude
that b-c-f is called for _every_ change, just as I did ~10 years ago.

> It intentionally refrains from saying "any and all modifications", and
> instead tries to be more vague.  Do you still think this is not good
> enough?  Because if you do, I don't see how we can say anything more
> accurate and yet avoid misleading the reader.

How can accurate documentation mislead?

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-19  8:45                                               ` Alan Mackenzie
@ 2016-08-19  9:12                                                 ` Eli Zaretskii
  2016-08-19  9:21                                                   ` Stefan Monnier
  2016-08-19  9:19                                                 ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-19  9:12 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: monnier, emacs-devel

> Date: Fri, 19 Aug 2016 08:45:26 +0000
> Cc: Stefan Monnier <monnier@iro.umontreal.ca>, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > One questionable place is insert-file-contents: it deliberately never
> > calls the before-change-functions when it deletes portions of the
> > text, only when it inserts text.  I don't really understand the
> > reasons behind your insisting on before-change-functions being called
> > before any changes in this case, but maybe a simple way out would be
> > to announce at the beginning of the function that the entire range
> > between point-min and point-max is about to be changed, when REPLACE
> > is non-nil.
> 
> That might create difficulties for CC Mode.  CC Mode now recognises when
> b-c-f isn't called at all, but isn't, as far as I've thought it through,
> prepared to deal with b-c-f with inaccurate arguments.

The arguments are not inaccurate: what insert-file-contents does in
that case is really replace the text between point-min and point-max
with what's in the file on disk.  That it includes internal
optimizations which actually try to make minimal changes is just that
-- an optimization.  Modes that hook the changes cannot depend on
internal optimizations like that.

More generally, since CC mode already knows how to recalculate
everything when a buffer is reverted, this should no longer be an
issue.

> > In message_dolog, which is called by any code which logs a message in
> > *Messages*, we never call the before-change-functions for the
> > *Messages* buffer, but we do call the after-change-functions for it.
> > Problem or not?
> 
> "Change Hooks" in the Elisp manual states that b-c-f and a-c-f are not
> called for the *Messages* buffer.  So I would say calling a-c-f here is a
> bug.

You are reading the manual too literally.

> >   This variable holds a list of functions to call when Emacs is about
> >   to modify a buffer.
> 
> Somebody wanting to use b-c-f and reading that text is likely to conclude
> that b-c-f is called for _every_ change, just as I did ~10 years ago.

Then they will be wrong, because the text doesn't say so.

> > It intentionally refrains from saying "any and all modifications", and
> > instead tries to be more vague.  Do you still think this is not good
> > enough?  Because if you do, I don't see how we can say anything more
> > accurate and yet avoid misleading the reader.
> 
> How can accurate documentation mislead?

By using terminology that is not rigorously defined.  Like "buffer
modification", for example.  You yourself say that
set-buffer-multibyte shouldn't call the modification hooks, but that
function surely does perform "buffer modifications" in some sense of
that term.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-19  8:45                                               ` Alan Mackenzie
  2016-08-19  9:12                                                 ` Eli Zaretskii
@ 2016-08-19  9:19                                                 ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-19  9:19 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Eli Zaretskii, emacs-devel

>> This variable holds a list of functions to call when Emacs is about
>> to modify a buffer.
> Somebody wanting to use b-c-f and reading that text is likely to conclude
> that b-c-f is called for _every_ change, just as I did ~10 years ago.

That's a correct reading, and the code has been obeying this rule
"forever", except for a few bugs maybe, the only remaining one
apparently being the one in insert-file-contents.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-19  9:12                                                 ` Eli Zaretskii
@ 2016-08-19  9:21                                                   ` Stefan Monnier
  2016-08-19  9:39                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-19  9:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Alan Mackenzie, emacs-devel

>> Somebody wanting to use b-c-f and reading that text is likely to conclude
>> that b-c-f is called for _every_ change, just as I did ~10 years ago.
> Then they will be wrong, because the text doesn't say so.

I think we're talking about different notions of "every change".
More specifically, I think I don't understand what Alan thinks "every
change" means, and I suspect that he doesn't understand what I mean by
that either.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-19  9:21                                                   ` Stefan Monnier
@ 2016-08-19  9:39                                                     ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-19  9:39 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: acm, emacs-devel

> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> Cc: Alan Mackenzie <acm@muc.de>, emacs-devel@gnu.org
> Date: Fri, 19 Aug 2016 05:21:04 -0400
> 
> >> Somebody wanting to use b-c-f and reading that text is likely to conclude
> >> that b-c-f is called for _every_ change, just as I did ~10 years ago.
> > Then they will be wrong, because the text doesn't say so.
> 
> I think we're talking about different notions of "every change".

Exactly.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-07-31 15:03 ` Eli Zaretskii
  2016-07-31 17:28   ` Alan Mackenzie
  2016-08-09 15:01   ` Alan Mackenzie
@ 2016-08-19 14:51   ` Phillip Lord
  2016-08-30  1:15     ` Stefan Monnier
  2 siblings, 1 reply; 189+ messages in thread
From: Phillip Lord @ 2016-08-19 14:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: ofv, Alan Mackenzie, rcopley, emacs-devel




Eli Zaretskii <eliz@gnu.org> writes:
> My interpretation of these two variables is that they are two hooks
> provided for different kinds of features, because hooking into both
> should not generally be required.  It should suffice for an
> application that wants to react to a change in a buffer to hook into
> after-change-functions only.


My apologies for jumping into the discussion so late, but I have been
travelling.

I make use of both b-c-f and a-c-f in my package called lentic. This
percolates changes in one buffer into another which is related but may
not be indentical to the first.

To enable this, I have to be able to convert between cognate positions
in the two buffers; that is the positions which are equivalent in the
two buffers. But I have to do this BEFORE the changes occur, because at
this point the two buffers are in a consistent state. This is not true
after the change has happened in one buffer and before it has been
percolated to the next.

Having b-c-f and a-c-f paired is not essential for this, but is (or
would be) greately helpful. It would also be good if the values passed
to b-c-f and a-c-f were consistent. Unfortunately this is not true
either (subst-char-in-region at least is guilty here, passing different
"end" positions in b-c-f and a-c-f).

I use the following logic to detect when b-c-f and a-c-f are "skewed" --
that is inconsistent with each other. "start" and "stop" are the
parameters of a-c-f and "length-before" is the value of the length
parameter of b-c-f called immediately before a-c-f.

 (or
                ;; previously this was not skewed if no region, but actually,
                ;; if there is no region we need to copy everything, we can
                ;; also do by declaring skew -- this is important for the
                ;; multi-lentic situation
                (not (or start stop length-before))
                ;; skews only occur in insertions which result in a positive
                ;; length-before. This also picks up no-insertion changes
                (and (< 0 length-before)
                     ;; = start stop means we have a deletion because
                     ;; there is no range after. Deletions seem to be
                     ;; safe.
                     (not (= start stop))))

This seems to work for me, but it's guess work. I do not understand
quite why it works, and there are (undoubtly) some cases where it does
not.

I realise that there may be practical difficulties in making the two
hooks consistent, although I think that this would be a laudable aim.
But failing this, it would be at least nice to know when the hooks are
not consistent; either in documentation, or better as a parameter, so I
could stop guessing.

The implications for lentic are significant; even though I can generally
avoid issues with the code above, the assumption that the whole buffer
is dirty generates a large amount of undo information. Fortuantely, it
happens only rarely, or this would simply prevent my approach from
working.

Which leads me to two conclusions:

1) being able to know when b-c-f and a-c-f are not paired or consistent
would be useful

2) decreasing the number of times these occurs would be useful, even if
it cannot be removed entirely.

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-11 16:43                                                     ` Stefan Monnier
@ 2016-08-28 11:23                                                       ` Daniel Colascione
  2016-08-28 15:01                                                         ` Stefan Monnier
                                                                           ` (2 more replies)
  0 siblings, 3 replies; 189+ messages in thread
From: Daniel Colascione @ 2016-08-28 11:23 UTC (permalink / raw)
  To: Stefan Monnier, Alan Mackenzie; +Cc: emacs-devel

On 08/11/2016 09:43 AM, Stefan Monnier wrote:
>> That is the current status, yes.  In the bug which gave rise to this
>> discussion, bug #24094, a certain change did not call b-c-f at all.
>
> Right, but that's a bug, not a misfeature we want to document.
>
>> The Elisp manual, up until yesterday, documented implicitly that b-c-f
>> and a-c-f were paired.
>
> No: you read it as documenting this implicitly, but that's a misunderstanding.

Alan's interpretation is the text is the natural one, and it's the one I 
had as well. It's a technical specification, not some kind of allegory. 
It's meant to be taken literally. There is nothing in the old manual to 
hint at the more complex reality of the situation, and the additional 
text just confuses the issue.

Besides, you haven't fixed the docstring, which still suggests that 
b-c-f is called before every change. (And a "change" must be anything 
that results in a-c-f being called.)

Alan is absolutely correct that current Emacs behavior should count as a 
bug. The behavior Alan wants, which is also the behavior XEmacs 
provides, and the behavior the manual suggestions on plain reading, is 
also the most elegant and useful behavior for these hooks.

Eli's original argument for not balancing b-c-f with a-c-f is the 
delicacy of other Emacs code, but this specific change is almost 
certainly safe, considering that b-c-f is almost always balanced with 
a-c-f already. Alan's given plenty examples of legitimate pieces of code 
that can break if b-c-f is not called for a given a-c-f.

What pieces of code could conceivably break if Emacs balances 
currently-unbalanced a-c-f calls?

>
>>> Furthermore there is no evidence that you "MUST".
>>> I gave various examples of ways you can live with only a-c-f.
>> Vague hand-waving is what I remember.
>
> That's because you don't want to think about it seriously: Of course
> it's not in the form of a patch to CC-mode that passes all your tests
> plus various performance assessments, no.  But those "vague hand-waving"
> refer to techniques used in actual code in various major modes facing
> similar problems.
>
>> You know full well what I mean.  By the time you get to a-c-f the
>> deletion as announced is a hollowed out husk, all its details except for
>> its position and size having been lost.
>
> As mentioned in my so-called "hand-waving", any details you may need can
> be stored somewhere for use.

Is it really better to force that complexity (which, in the limit, 
amounts to full shadow buffers) onto mode authors instead of changing 
Emacs to balance b-c-f with a-c-f 100% of the time instead of 99%?

> But there's no reason your code could *require* this data for correct
> behavior, since your code also has to handle the more general case where
> all the text after BEG has been replaced by something else which may or
> may not include similar contents and may or may not already include some
> text-properties like `syntax-table'.
>
>> What you and Eli are asserting is that one NEVER IN ANY CIRCUMSTANCES
>> needs to know the full details of a buffer modification, and no program
>> now or in the future ever will.
>
> Exactly.  And that's because the code has to handle the previously
> mentioned general case anyway.
>
>> With the recent change in documentation, Emacs 25.1 has become a less
>> powerful programming system, one in which these details cannot
>> be determined.
>
> Nope.  The documentation is just more honest than before.

It's also self-contradictory: upon calling syntax-ppss, Emacs installs a 
before-change-function, which in a mode that perfectly legitimately has 
an after-change-function, violates the rule that we use one set of 
functions or another.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-28 11:23                                                       ` Daniel Colascione
@ 2016-08-28 15:01                                                         ` Stefan Monnier
  2016-08-28 22:16                                                           ` Daniel Colascione
  2016-08-28 22:36                                                         ` Stefan Monnier
  2016-08-30 13:30                                                         ` Phillip Lord
  2 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-28 15:01 UTC (permalink / raw)
  To: emacs-devel

> Besides, you haven't fixed the docstring, which still suggests that b-c-f is
> called before every change. (And a "change" must be anything that results in
> a-c-f being called.)

It doesn't just suggest it, it says so, and rightly so.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-28 15:01                                                         ` Stefan Monnier
@ 2016-08-28 22:16                                                           ` Daniel Colascione
  2016-08-28 22:44                                                             ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-28 22:16 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 08/28/2016 08:01 AM, Stefan Monnier wrote:
>> Besides, you haven't fixed the docstring, which still suggests that b-c-f is
>> called before every change. (And a "change" must be anything that results in
>> a-c-f being called.)
>
> It doesn't just suggest it, it says so, and rightly so.

So will insdel.c or the docstring change?

FWIW, there *is* a certain elegance to the idea of the "forget 
everything after the first bit that changed" model of change tracking, 
but as long as b-c-f exists, it might as well work consistently.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-28 11:23                                                       ` Daniel Colascione
  2016-08-28 15:01                                                         ` Stefan Monnier
@ 2016-08-28 22:36                                                         ` Stefan Monnier
  2016-08-30 13:30                                                         ` Phillip Lord
  2 siblings, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-28 22:36 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Alan Mackenzie, emacs-devel

>> No: you read it as documenting this implicitly, but that's
>> a misunderstanding.
> Alan's interpretation is the text is the natural one, and it's the one I had
> as well.

If you say so.  I must say I don't know/understand what is his
interpretation, so if you can give details it would help.  E.g. give us
a concrete scenario that currently happens in Emacs and which you think
is incompatible with the description.

[ Tho, please note that we already know about 1 such scenario (the lack
  of b-c-f from insert-file-contents with `replace' non-nil and where
  the new content has no new text but has simply some part of the file
  deleted) which we all agree is a bug.  ]

> What pieces of code could conceivably break if Emacs balances
> currently-unbalanced a-c-f calls?

That's the wrong question.  A more interesting question could be: how
can we make those hooks always perfectly balanced even in the most twisted
cases (e.g. when a b/a-c-f call itself makes a change to the buffer),
and without undue performance penalty.  Another one would be: who would
write such a patch and then make sure that this patch doesn't introduce
other bugs?  On the sideline: the only known case which would benefit,
really, is that of Phillip Lord (because, as best I can see,
Alan's case would benefit much more from getting rid of this assumption
altogether (although Alan himself wouldn't benefit as much because he'd
first have to learn to appreciate this other way to deal with the
problem)).

> Is it really better to force that complexity (which, in the limit, amounts
> to full shadow buffers)

What complexity?  Compare the complexity of CC-mode with that of
cperl-mode or perl-mode.  I can guarantee you that it's actually
*simpler* to give up on the idea of perfectly matched b/a-c-f calls for
purposes of syntax highlighting and parsing.

> legitimately has an after-change-function, violates the rule that we use one
> set of functions or another.

There's no such rule.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-28 22:16                                                           ` Daniel Colascione
@ 2016-08-28 22:44                                                             ` Stefan Monnier
  2016-08-28 23:11                                                               ` Daniel Colascione
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-28 22:44 UTC (permalink / raw)
  To: emacs-devel

>>> Besides, you haven't fixed the docstring, which still suggests that b-c-f is
>>> called before every change. (And a "change" must be anything that results in
>>> a-c-f being called.)
>> It doesn't just suggest it, it says so, and rightly so.
> So will insdel.c or the docstring change?

I don't know what you're referring to or how that relates to the quoted text.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-28 22:44                                                             ` Stefan Monnier
@ 2016-08-28 23:11                                                               ` Daniel Colascione
  2016-08-29  0:09                                                                 ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-28 23:11 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 08/28/2016 03:44 PM, Stefan Monnier wrote:
>>>> Besides, you haven't fixed the docstring, which still suggests that b-c-f is
>>>> called before every change. (And a "change" must be anything that results in
>>>> a-c-f being called.)
>>> It doesn't just suggest it, it says so, and rightly so.
>> So will insdel.c or the docstring change?
>
> I don't know what you're referring to or how that relates to the quoted text.

Sorry --- let me try adding more context. According to the very long 
thread above, I think these are the things everyone agrees to be true:

1) b-c-f isn't currently balanced with a-c-f in the insdel.c implementation

2) b-c-f isn't currently guaranteed to be called at all before any given 
call to a-c-f (e.g., the C-x C-f case)

2) the documentation suggests that a-c-f and b-c-f are balanced

3) many people, Alan and me included, were under the impression that 
b-c-f and a-c-f were balanced and wrote code accordingly

AIUI, Eli's position is that the current behavior should not change at 
all, because making changes at this level is too risky. The 
documentation should change to reflect #1 and #2. Your position is that 
#2 is a bug, but #1 is not, and the documentation needs to change. My 
position, and Alan's, is that #1 and #2 are both bugs and the current 
documentation is fine.

The status quo is that the documentation misleads developers about what 
Emacs actually does. I don't think it's fair to suggest that both Alan 
and I both just misunderstood the documentation.

So what do you propose doing? Upthread, I explained why I think that 
fixing both #1 and #2 is pretty low-risk.




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-28 23:11                                                               ` Daniel Colascione
@ 2016-08-29  0:09                                                                 ` Stefan Monnier
  2016-08-29  3:18                                                                   ` Daniel Colascione
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-29  0:09 UTC (permalink / raw)
  To: emacs-devel

> 1) b-c-f isn't currently balanced with a-c-f in the insdel.c implementation

There's no guarantee that it be balanced, indeed.

> 2) b-c-f isn't currently guaranteed to be called at all before any given
> call to a-c-f (e.g., the C-x C-f case)

It is guaranteed, modulo bugs (the insert-file-contents (with replace) case).

> 2) the documentation suggests that a-c-f and b-c-f are balanced

I don't see where in the documentation it suggests it.

> 3) many people, Alan and me included, were under the impression that b-c-f
> and a-c-f were balanced and wrote code accordingly

Ah, so you too have code which makes this assumption.  Could you point
to it, explaining what it does and why it makes this assumption, so we
have a better picture of why it could be useful?

> AIUI, Eli's position is that the current behavior should not change at all,
> because making changes at this level is too risky.

I don't think he said "at all", but just that it's tricky to make such
changes, so they had better be backed by really good reasons.

> Your position is that #2 is a bug, but #1 is not, and the
> documentation needs to change.

Almost: I don't see the need to change the doc because I don't see where
it misleads.

> So what do you propose doing? Upthread, I explained why I think that fixing
> both #1 and #2 is pretty low-risk.

The problem is that changing the code w.r.t b/a-c-f might cause
*other* changes.  Clearly making them perfectly balanced and paired
should not *in itself* introduce any bugs: the bugs we're afraid of are
the accompanying unintended changes.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29  0:09                                                                 ` Stefan Monnier
@ 2016-08-29  3:18                                                                   ` Daniel Colascione
  2016-08-29 13:00                                                                     ` Stefan Monnier
  2016-08-29 14:50                                                                     ` Eli Zaretskii
  0 siblings, 2 replies; 189+ messages in thread
From: Daniel Colascione @ 2016-08-29  3:18 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 08/28/2016 05:09 PM, Stefan Monnier wrote:
>> 1) b-c-f isn't currently balanced with a-c-f in the insdel.c implementation
>
> There's no guarantee that it be balanced, indeed.
>
>> 2) b-c-f isn't currently guaranteed to be called at all before any given
>> call to a-c-f (e.g., the C-x C-f case)
>
> It is guaranteed, modulo bugs (the insert-file-contents (with replace) case).

Sure. The current implementation provides neither property though.

>> 2) the documentation suggests that a-c-f and b-c-f are balanced
>
> I don't see where in the documentation it suggests it.

See below.

>> 3) many people, Alan and me included, were under the impression that b-c-f
>> and a-c-f were balanced and wrote code accordingly
>
> Ah, so you too have code which makes this assumption.  Could you point
> to it, explaining what it does and why it makes this assumption, so we
> have a better picture of why it could be useful?

Same as Alan's --- examining the buffer before the change to see which 
brace-delimited scopes need to be invalidated. It's not possible to do 
that in a-c-f because the text that was changed is unavailable in a-c-f. 
Emacs core also contains a lot of code that looks fragile under 
asymmetric b-c-f behavior: see tex-mode, org, and viper. (I'm not 
claiming that these modes are broken, but it's not obvious from the code 
that they aren't broken.)

Yes, it's always possible, with enough shadowing of buffer contents, to 
rely on a-c-f alone. I think. But since Emacs already *has* the b-c-f 
feature, since it's pretty widely used, and since it *almost* works as 
expected today, it's be best to just change the behavior instead of 
sending a "gotcha! The manual is correct only under close reading!" 
message to everyone who uses b-c-f.

>> AIUI, Eli's position is that the current behavior should not change at all,
>> because making changes at this level is too risky.
>
> I don't think he said "at all", but just that it's tricky to make such
> changes, so they had better be backed by really good reasons.
>
>> Your position is that #2 is a bug, but #1 is not, and the
>> documentation needs to change.
> Please trust me that the documentation misleads.
> Almost: I don't see the need to change the doc because I don't see where
> it misleads.

b-c-f and a-c-f are symmetric in name and signature. b-c-f is documented 
as "List of functions to call before each text change." a-c-f is 
documented as "List of functions to call after each text change." The 
elisp manual documentation is similarly symmetric. This symmetry 
produces an expectation that the behavior is symmetric, and this 
expectation is reinforced by how the observed behavior is almost always 
symmetric in practice. Symmetric behavior here is also what intuitively 
makes sense.

Please believe me when I say that the current documentation misleads.

I mean, imagine you were writing a home automation system and saw 
before-doorbell-functions and after-doorbell-functions hooks, read the 
documentation, and saw that the former is a list of functions to be 
called "before the doorbell chime rings" and the latter is a list of 
functions to be called "after the doorbell chime rings".

Imagine that when you tested these hooks, you saw that the b-d-f were 
indeed run before you heard the chime and a-d-f functions after. What on 
earth would make you suspect that this behavior wouldn't be the case in 
some circumstances? Wouldn't you treat a failure to run b-d-f if the 
doorbell butter were pressed forcefully as a bug? Wouldn't you think it 
strange if pressing the doorbell button quickly five times in a row 
after 9pm on Tuesdays produced five chimes, five calls to a-d-f, but 
only one call to b-d-f?

Sure, I guess you could argue that current Emacs behavior is consistent 
with the manual, but it's not what anyone would reasonably expect, and 
the current behavior is surprising even to people who have been writing 
elisp for a long time. It's like that joke about the mathematician who 
sees only half of one black sheep in Scotland.

A feature that almost works as expected --- except in certain weird 
cases where it corrupts your state --- is at best an attractive nuisance.

>> So what do you propose doing? Upthread, I explained why I think that fixing
>> both #1 and #2 is pretty low-risk.
>
> The problem is that changing the code w.r.t b/a-c-f might cause
> *other* changes.  Clearly making them perfectly balanced and paired
> should not *in itself* introduce any bugs: the bugs we're afraid of are
> the accompanying unintended changes.

I was under the impression that Eli's concern was with the effect of the 
b-c-f change itself, not with bugs that might be introduced by the 
change. I'm confident that with enough review, the core code could be 
changed to make b-c-f and a-c-f symmetric without causing weird bugs 
elsewhere. The necessary refactoring will probably make the logic 
cleaner as well.

Of course there's a risk that changing b-c-f will itself produce weird 
side effects, but I have a hard time seeing how any code could actually 
depend on the current surprising behavior.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29  3:18                                                                   ` Daniel Colascione
@ 2016-08-29 13:00                                                                     ` Stefan Monnier
  2016-08-29 14:51                                                                       ` Eli Zaretskii
  2016-08-29 15:14                                                                       ` Daniel Colascione
  2016-08-29 14:50                                                                     ` Eli Zaretskii
  1 sibling, 2 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-29 13:00 UTC (permalink / raw)
  To: emacs-devel

>> It is guaranteed, modulo bugs (the insert-file-contents (with
>> replace) case).
> Sure. The current implementation provides neither property though.

That's OK.  We're talking about the doc and the intended behavior.
Bugs are part of life.

>> Ah, so you too have code which makes this assumption.  Could you point
>> to it, explaining what it does and why it makes this assumption, so we
>> have a better picture of why it could be useful?
> Same as Alan's --- examining the buffer before the change to see which
> brace-delimited scopes need to be invalidated.

I need more details.

> Emacs core also contains a lot of code that looks fragile under
> asymmetric b-c-f behavior: see tex-mode, org, and viper. (I'm not
> claiming that these modes are broken, but it's not obvious from the
> code that they aren't broken.)

tex-mode's b-c-f doesn't care about when or how any a-f-c gets run or if
it even get run at all.  It just sets some text-properties lazily
(because those properties are only needed when and where a change
happens, so they can be set via b-c-f rather than setting them eagerly
over the whole buffer right from the start).

No idea about org, as for Viper I'm not completely sure what it's trying
to do, but the code looks fiddly (with or without b/a-c-f's asymmetry)
so I'd expect breakage in corner cases anyway.

>> Almost: I don't see the need to change the doc because I don't see where
>> it misleads.
> b-c-f and a-c-f are symmetric in name and signature. b-c-f is documented as
> "List of functions to call before each text change." a-c-f is documented as
> "List of functions to call after each text change." The elisp manual
> documentation is similarly symmetric. This symmetry produces an expectation
> that the behavior is symmetric, and this expectation is reinforced by how
> the observed behavior is almost always symmetric in practice. Symmetric
> behavior here is also what intuitively makes sense.
>
> Please believe me when I say that the current documentation misleads.

OK, so you agree that the documentation does not say they are
properly paired.  You just extrapolate it.

I agree there's such a risk that the reader extrapolates in the way you
described, which is why the current documentation states explicitly that
they're not always paired:

      Do @emph{not} expect the before-change hooks and the after-change
    hooks be called in balanced pairs around each buffer change.  Also

I think it's pretty clear.

> A feature that almost works as expected --- except in certain weird cases
> where it corrupts your state --- is at best an attractive nuisance.

I don't claim that the lack of symmetry is a feature.  But fixing it is
not easy.

Furthermore, the cases I've seen of code designs which wants this
behavior tend to be brittle and overly complicated, compared to
alternative designs which don't rely on this behavior.

I guess a way to "fix" it would be to add a random fudge factor to the
b-c-f calls, plus add random dummy calls to b-c-f, and sprinkle the
lisp/*.el code with combine-after-change-calls.  This way, the "properly
paired up" case will be much more exceptional.

> I was under the impression that Eli's concern was with the effect of
> the b-c-f change itself, not with bugs that might be introduced by
> the change.

I can't speak for Eli, but at least that's not my worry.

> I'm confident that with enough review, the core code could be changed
> to make b-c-f and a-c-f symmetric without causing weird
> bugs elsewhere.

Sure.  But I see more benefits in changing the few places that
mistakenly rely on this pairing.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29  3:18                                                                   ` Daniel Colascione
  2016-08-29 13:00                                                                     ` Stefan Monnier
@ 2016-08-29 14:50                                                                     ` Eli Zaretskii
  2016-08-29 15:30                                                                       ` Daniel Colascione
                                                                                         ` (3 more replies)
  1 sibling, 4 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-29 14:50 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: monnier, emacs-devel

> From: Daniel Colascione <dancol@dancol.org>
> Date: Sun, 28 Aug 2016 20:18:32 -0700
> 
>     Please trust me that the documentation misleads.

You are welcome to suggest more accurate wording that describes the
current implementation.

> b-c-f and a-c-f are symmetric in name and signature. b-c-f is documented as "List of functions to call before each text change." a-c-f is documented as "List of functions to call after each text change." The elisp manual documentation is similarly symmetric. This symmetry produces an expectation that the behavior is symmetric, and this expectation is reinforced by how the observed behavior is almost always symmetric in practice. Symmetric behavior here is also what intuitively makes sense.

This is a naïve interpretation of what a "change" means and entails.
In reality, some changes are done with a single call to an insdel
function, while others need multiple calls that delete and insert text
piecemeal.  Thus the need to call the hooks before and after each
insdel call only sometimes.

Your bell analogy has the same issue: internally, the "chime" is in
fact a complex array of transitions and changes, not an atomic effect.
By treating it as an atomic unit, you actually uphold the view taken
by the current implementation, which attempts to minimize the number
of hook calls per change.

> Sure, I guess you could argue that current Emacs behavior is consistent with the manual, but it's not what anyone would reasonably expect, and the current behavior is surprising even to people who have been writing elisp for a long time.

Surprising or not, the existing implementation is in use for many
years, and until now no complaints were presented about it.  And even
now we have a single complaint from a single use case of a single
package (which meanwhile fixed the problem without any core changes).
Which is ample evidence that the existing implementation does a good
job after all.

> I'm confident that with enough review, the core code could be changed to make b-c-f and a-c-f symmetric without causing weird bugs elsewhere. The necessary refactoring will probably make the logic cleaner as well.
> 
> Of course there's a risk that changing b-c-f will itself produce weird side effects, but I have a hard time seeing how any code could actually depend on the current surprising behavior.

That's exactly the nonchalant attitude towards changes in core that
explains why, after 30-odd years of development, which should have
given us an asymptotically more and more stable Emacs, we still
succeed quite regularly to break core code and basic features, while
"confidently" relying on our mythical abilities to refactor correctly
without any serious testing coverage.  Never again.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 13:00                                                                     ` Stefan Monnier
@ 2016-08-29 14:51                                                                       ` Eli Zaretskii
  2016-08-29 15:50                                                                         ` Stefan Monnier
  2016-08-29 15:14                                                                       ` Daniel Colascione
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-29 14:51 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Mon, 29 Aug 2016 09:00:40 -0400
> 
> > I was under the impression that Eli's concern was with the effect of
> > the b-c-f change itself, not with bugs that might be introduced by
> > the change.
> 
> I can't speak for Eli, but at least that's not my worry.

I actually don't understand the difference: how is "the effect of the
change itself" different from "bugs that might be introduced" by it.
Sounds like the latter is a subset of the former?

> > I'm confident that with enough review, the core code could be changed
> > to make b-c-f and a-c-f symmetric without causing weird
> > bugs elsewhere.
> 
> Sure.  But I see more benefits in changing the few places that
> mistakenly rely on this pairing.

Agreed.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 13:00                                                                     ` Stefan Monnier
  2016-08-29 14:51                                                                       ` Eli Zaretskii
@ 2016-08-29 15:14                                                                       ` Daniel Colascione
  2016-08-29 15:44                                                                         ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-29 15:14 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

On 08/29/2016 06:00 AM, Stefan Monnier wrote:
> Furthermore, the cases I've seen of code designs which wants this
> behavior tend to be brittle and overly complicated, compared to
> alternative designs which don't rely on this behavior.
>
> I guess a way to "fix" it would be to add a random fudge factor to the
> b-c-f calls, plus add random dummy calls to b-c-f, and sprinkle the
> lisp/*.el code with combine-after-change-calls.  This way, the "properly
> paired up" case will be much more exceptional.

You can't be serious.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 14:50                                                                     ` Eli Zaretskii
@ 2016-08-29 15:30                                                                       ` Daniel Colascione
  2016-08-29 16:20                                                                         ` Eli Zaretskii
  2016-08-30 14:12                                                                       ` Phillip Lord
                                                                                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-29 15:30 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel

On 08/29/2016 07:50 AM, Eli Zaretskii wrote:
>> From: Daniel Colascione <dancol@dancol.org>
>> Date: Sun, 28 Aug 2016 20:18:32 -0700
>>
>>     Please trust me that the documentation misleads.
>
> You are welcome to suggest more accurate wording that describes the
> current implementation.

Just mark b-c-f deprecated.

>> b-c-f and a-c-f are symmetric in name and signature. b-c-f is documented as "List of functions to call before each text change." a-c-f is documented as "List of functions to call after each text change." The elisp manual documentation is similarly symmetric. This symmetry produces an expectation that the behavior is symmetric, and this expectation is reinforced by how the observed behavior is almost always symmetric in practice. Symmetric behavior here is also what intuitively makes sense.
>
> This is a naïve interpretation of what a "change" means and entails.

It doesn't matter what a "change" means and entails. Whatever a "change" 
is, b-c-f and a-c-f use the same word for it, and I've already explained 
why it's natural to suppose symmetry between these hooks. In order for 
b-c-f and a-c-f to be asymmetric, the definition of the word "change" 
needs to somehow change.

Do you really not understand why many people would find the current 
behavior surprising? You have at least *three* people independently 
annoyed by it: Alan, Phillip Lord, and me.

>> Sure, I guess you could argue that current Emacs behavior is consistent with the manual, but it's not what anyone would reasonably expect, and the current behavior is surprising even to people who have been writing elisp for a long time.
>
> Surprising or not, the existing implementation is in use for many
> years, and until now no complaints were presented about it.  And even
> now we have a single complaint from a single use case of a single
> package (which meanwhile fixed the problem without any core changes).
> Which is ample evidence that the existing implementation does a good
> job after all.

The current implementation is buggy. Even Stefan agrees that it 
currently contains bona fide bugs (the file visit case). These bugs 
produce difficult-to-diagnose user bugs reports. that have generated 
real bug reports. The current implementation does not serve the needs of 
its users.

I mean, you could just declare the current implementation correct and 
point to workarounds as evidence of the fact --- but that's like 
declaring a drain unclogged by definition and pointing to the plunger as 
evidence.

>> I'm confident that with enough review, the core code could be changed to make b-c-f and a-c-f symmetric without causing weird bugs elsewhere. The necessary refactoring will probably make the logic cleaner as well.
>>
>> Of course there's a risk that changing b-c-f will itself produce weird side effects, but I have a hard time seeing how any code could actually depend on the current surprising behavior.
>
> That's exactly the nonchalant attitude towards changes in core that
> explains why, after 30-odd years of development, which should have
> given us an asymptotically more and more stable Emacs, we still
> succeed quite regularly to break core code and basic features, while
> "confidently" relying on our mythical abilities to refactor correctly
> without any serious testing coverage.

The modern software engineering approach to preventing regressions is 
test automation. Insisting on adding a test as part of the change is 
reasonable. Forbidding all change, no matter how carefully done, is not.

 >  Never again.

The surest way to make sure a computer doesn't do anything wrong is to 
turn it off.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 15:14                                                                       ` Daniel Colascione
@ 2016-08-29 15:44                                                                         ` Stefan Monnier
  2016-08-30 14:07                                                                           ` Phillip Lord
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-29 15:44 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: emacs-devel

>> I guess a way to "fix" it would be to add a random fudge factor to the
>> b-c-f calls, plus add random dummy calls to b-c-f, and sprinkle the
>> lisp/*.el code with combine-after-change-calls.  This way, the "properly
>> paired up" case will be much more exceptional.
> You can't be serious.

If it can finally get us rid of people who insist they want exactly
paired/matched/symmetric b/a-c-f, then I'd willing to do that, yes.

AFAICT the result would be simpler, cleaner, and more robust code, since
instead of trying to think of the various different ways a buffer can
change here or there, the coder would be forced to step back and think
how to handle the general case.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 14:51                                                                       ` Eli Zaretskii
@ 2016-08-29 15:50                                                                         ` Stefan Monnier
  2016-08-29 16:22                                                                           ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-29 15:50 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

>> > I was under the impression that Eli's concern was with the effect of
>> > the b-c-f change itself, not with bugs that might be introduced by
>> > the change.
>> I can't speak for Eli, but at least that's not my worry.
> I actually don't understand the difference: how is "the effect of the
> change itself" different from "bugs that might be introduced" by it.
> Sounds like the latter is a subset of the former?

The request is to change the way b-c-f and a-c-f are run such that
they're always exactly paired.  Any patch which implements such a change
could have any number of other impacts.  So we can divide the impacts of such
a patch into 2 parts:
- the part which changes b-c-f and a-c-f to be exactly paired.
- the rest.

I think the first part should be 100% safe, because any code which works
correctly with the current looser behavior of b/a-c-f should also work
correctly with the tighter behavior.  Of course, there might be code out
there which relies on the details of the current behavior b/a-c-f, but
I'm not worried about that at all.

"The rest" is the more likely source of worry.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 15:30                                                                       ` Daniel Colascione
@ 2016-08-29 16:20                                                                         ` Eli Zaretskii
  2016-08-29 16:26                                                                           ` Daniel Colascione
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-29 16:20 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: monnier, emacs-devel

> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Mon, 29 Aug 2016 08:30:21 -0700
> 
> >> b-c-f and a-c-f are symmetric in name and signature. b-c-f is documented as "List of functions to call before each text change." a-c-f is documented as "List of functions to call after each text change." The elisp manual documentation is similarly symmetric. This symmetry produces an expectation that the behavior is symmetric, and this expectation is reinforced by how the observed behavior is almost always symmetric in practice. Symmetric behavior here is also what intuitively makes sense.
> >
> > This is a naïve interpretation of what a "change" means and entails.
> 
> It doesn't matter what a "change" means and entails. Whatever a "change" 
> is, b-c-f and a-c-f use the same word for it, and I've already explained 
> why it's natural to suppose symmetry between these hooks. In order for 
> b-c-f and a-c-f to be asymmetric, the definition of the word "change" 
> needs to somehow change.

Of course, you have changed the subject.

> Do you really not understand why many people would find the current 
> behavior surprising? You have at least *three* people independently 
> annoyed by it: Alan, Phillip Lord, and me.

It doesn't matter what I understand or not, because that's not the
issue at hand.  We are talking about code that runs virtually
unchanged for many years.  Making significant changes in it needs a
good reason.  When such good reasons emerge, we can discuss whether
they justify the risks.  For now, the reasons presented do not.

> The current implementation is buggy.

Every piece of software is buggy.  That doesn't mean it's useless or
must be refactored the heck out of.

> (the file visit case). These bugs produce difficult-to-diagnose user
> bugs reports. that have generated real bug reports.

Those bugs were fixed.

> I mean, you could just declare the current implementation correct and 
> point to workarounds as evidence of the fact --- but that's like 
> declaring a drain unclogged by definition and pointing to the plunger as 
> evidence.

I'm not interested in an argument about correctness.  That's not what
this is about.  You are changing the subject again.

> > That's exactly the nonchalant attitude towards changes in core that
> > explains why, after 30-odd years of development, which should have
> > given us an asymptotically more and more stable Emacs, we still
> > succeed quite regularly to break core code and basic features, while
> > "confidently" relying on our mythical abilities to refactor correctly
> > without any serious testing coverage.
> 
> The modern software engineering approach to preventing regressions is 
> test automation. Insisting on adding a test as part of the change is 
> reasonable. Forbidding all change, no matter how carefully done, is not.

No one have forbidden all change, and no one in their right minds
will.  Do you really not understand what the above is about?

>  >  Never again.
> 
> The surest way to make sure a computer doesn't do anything wrong is to 
> turn it off.

If you aren't interested in it doing anything useful, sure.  But I am,
so these simple solutions are wrong for me (and for all the rest of
Emacs users).

Of course, if those absurd "arguments" are the only ones you have
left, I guess this is EOD.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 15:50                                                                         ` Stefan Monnier
@ 2016-08-29 16:22                                                                           ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-29 16:22 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> Cc: emacs-devel@gnu.org
> Date: Mon, 29 Aug 2016 11:50:13 -0400
> 
> "The rest" is the more likely source of worry.

Yes.  And that is what I understood "the effect of the change" is
about.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 16:20                                                                         ` Eli Zaretskii
@ 2016-08-29 16:26                                                                           ` Daniel Colascione
  2016-08-29 17:01                                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-29 16:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel

On 08/29/2016 09:20 AM, Eli Zaretskii wrote:
>> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
>> From: Daniel Colascione <dancol@dancol.org>
>> Date: Mon, 29 Aug 2016 08:30:21 -0700
>>
>>>> b-c-f and a-c-f are symmetric in name and signature. b-c-f is documented as "List of functions to call before each text change." a-c-f is documented as "List of functions to call after each text change." The elisp manual documentation is similarly symmetric. This symmetry produces an expectation that the behavior is symmetric, and this expectation is reinforced by how the observed behavior is almost always symmetric in practice. Symmetric behavior here is also what intuitively makes sense.
>>>
>>> This is a naïve interpretation of what a "change" means and entails.
>>
>> It doesn't matter what a "change" means and entails. Whatever a "change"
>> is, b-c-f and a-c-f use the same word for it, and I've already explained
>> why it's natural to suppose symmetry between these hooks. In order for
>> b-c-f and a-c-f to be asymmetric, the definition of the word "change"
>> needs to somehow change.
>
> Of course, you have changed the subject.
>
>> Do you really not understand why many people would find the current
>> behavior surprising? You have at least *three* people independently
>> annoyed by it: Alan, Phillip Lord, and me.
>
> It doesn't matter what I understand or not, because that's not the
> issue at hand.  We are talking about code that runs virtually
> unchanged for many years.  Making significant changes in it needs a
> good reason.  When such good reasons emerge, we can discuss whether
> they justify the risks.  For now, the reasons presented do not.

What criteria are you using to determine whether a bug is sufficiently 
serious to fix? What would convince you that a change in this behavior 
is warranted?



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 16:26                                                                           ` Daniel Colascione
@ 2016-08-29 17:01                                                                             ` Eli Zaretskii
  2016-08-29 17:48                                                                               ` Daniel Colascione
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-29 17:01 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: monnier, emacs-devel

> From: Daniel Colascione <dancol@dancol.org>
> Date: Mon, 29 Aug 2016 09:26:38 -0700
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> 
> > We are talking about code that runs virtually
> > unchanged for many years.  Making significant changes in it needs a
> > good reason.  When such good reasons emerge, we can discuss whether
> > they justify the risks.  For now, the reasons presented do not.
> 
> What criteria are you using to determine whether a bug is sufficiently 
> serious to fix? What would convince you that a change in this behavior 
> is warranted?

I described up-thread what would constitute a good enough reason for
me to consider such changes for admission.  Here's the list again:

  . a bug that affects (i.e. breaks) the core code itself (e.g., see
    bug#5131 fixed in 00b6647 as a recent example related to insdel.c)
  . a problem that affects several Lisp packages for which there's no
    reasonably practical workaround/fix as part of the package itself
  . refactoring done as part of introducing a significant new feature

Please note that not every change/bugfix is required to pass such
scrutiny, only changes in code that is very central to Emacs
operation.  I think manipulation of buffer text, display engine, basic
file I/O, and encoding/decoding stuff are such areas.  Changes that
affect some aspects of more local, specialized behavior are normally
less risky.  IOW, there's still a judgment call needed in each case,
so that the above is applicable to as few changes as possible.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 17:01                                                                             ` Eli Zaretskii
@ 2016-08-29 17:48                                                                               ` Daniel Colascione
  2016-08-29 18:04                                                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-29 17:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel



On 08/29/2016 10:01 AM, Eli Zaretskii wrote:
>> From: Daniel Colascione <dancol@dancol.org>
>> Date: Mon, 29 Aug 2016 09:26:38 -0700
>> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
>>
>>> We are talking about code that runs virtually
>>> unchanged for many years.  Making significant changes in it needs a
>>> good reason.  When such good reasons emerge, we can discuss whether
>>> they justify the risks.  For now, the reasons presented do not.
>>
>> What criteria are you using to determine whether a bug is sufficiently
>> serious to fix? What would convince you that a change in this behavior
>> is warranted?
>
> I described up-thread what would constitute a good enough reason for
> me to consider such changes for admission.  Here's the list again:
>
>   . a bug that affects (i.e. breaks) the core code itself (e.g., see
>     bug#5131 fixed in 00b6647 as a recent example related to insdel.c)
>   . a problem that affects several Lisp packages for which there's no
>     reasonably practical workaround/fix as part of the package itself
>   . refactoring done as part of introducing a significant new feature

We have two separate bugs here. In order of severity:

1) Something b-c-f is not called _at_ _all_ before certain changes
2) Sometimes b-c-f is called once, then a-c-f is called multiple times, 
because internally, changes are split into several chunks, each of which 
gets its own a-c-f call

I can understand #2 being wontfix, but can you reconsider fixing #1? #1 
breaks the entire b-c-f model --- "hey, I'm about to modify the buffer, 
so throw away caches" ---- and can lead to anything with a cache flush 
in b-c-f (like syntax-ppss) not properly discarding out-of-date buffer 
information.

>
> Please note that not every change/bugfix is required to pass such
> scrutiny, only changes in code that is very central to Emacs
> operation.  I think manipulation of buffer text, display engine, basic
> file I/O, and encoding/decoding stuff are such areas.  Changes that
> affect some aspects of more local, specialized behavior are normally
> less risky.  IOW, there's still a judgment call needed in each case,
> so that the above is applicable to as few changes as possible.
>
>



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 17:48                                                                               ` Daniel Colascione
@ 2016-08-29 18:04                                                                                 ` Eli Zaretskii
  2016-08-29 18:16                                                                                   ` Eli Zaretskii
  2016-08-30  0:25                                                                                   ` Stefan Monnier
  0 siblings, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-29 18:04 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: monnier, emacs-devel

> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Mon, 29 Aug 2016 10:48:31 -0700
> 
> 1) Something b-c-f is not called _at_ _all_ before certain changes
> 2) Sometimes b-c-f is called once, then a-c-f is called multiple times, 
> because internally, changes are split into several chunks, each of which 
> gets its own a-c-f call
> 
> I can understand #2 being wontfix, but can you reconsider fixing #1?

There's only one such case, and the only package that's affected
(CC Mode) already worked around that case.

So, while I agreed that #1 should probably be fixed, and even
suggested how to do that in the least risky way, actually doing that
is not a priority, IMO, not until we have a very grave problem caused
by it.

> #1 breaks the entire b-c-f model --- "hey, I'm about to modify the
> buffer, so throw away caches" ---- and can lead to anything with a
> cache flush in b-c-f (like syntax-ppss) not properly discarding
> out-of-date buffer information.

That single case of #1 is revert-buffer, which conceptually throws
away the entire buffer and replaces it with what's on disk.  That it
actually keeps portions of the buffer is an optimization, but the
concept still stands.  So I don't see how it breaks the entire model,
at least not in practice.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 18:04                                                                                 ` Eli Zaretskii
@ 2016-08-29 18:16                                                                                   ` Eli Zaretskii
  2016-08-30  2:27                                                                                     ` Daniel Colascione
  2016-08-30  0:25                                                                                   ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-29 18:16 UTC (permalink / raw)
  To: dancol; +Cc: monnier, emacs-devel

> Date: Mon, 29 Aug 2016 21:04:42 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> 
> That single case of #1 is revert-buffer

Btw: not every call to revert-buffer hits this case.  Quite the
contrary: almost none of them do.  IOW, the situation where the
before-change hook is not called at all is very rare even if you only
consider the uses of revert-buffer.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 18:04                                                                                 ` Eli Zaretskii
  2016-08-29 18:16                                                                                   ` Eli Zaretskii
@ 2016-08-30  0:25                                                                                   ` Stefan Monnier
  2016-08-30  2:26                                                                                     ` Daniel Colascione
  2016-08-30  2:38                                                                                     ` Eli Zaretskii
  1 sibling, 2 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30  0:25 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Daniel Colascione, emacs-devel

> So, while I agreed that #1 should probably be fixed, and even
> suggested how to do that in the least risky way, actually doing that
> is not a priority, IMO, not until we have a very grave problem caused
> by it.

FWIW, I think it's important to fix the insert-file-contents case.
It breaks syntax-ppss, for example, although for various reasons of how
syntax-ppss is implemented and used, this happens to rarely show up.
[ So, yes, it's not top priority, but it should still be fixed.  ]

>> #1 breaks the entire b-c-f model --- "hey, I'm about to modify the
>> buffer, so throw away caches" ---- and can lead to anything with a
>> cache flush in b-c-f (like syntax-ppss) not properly discarding
>> out-of-date buffer information.
> That single case of #1 is revert-buffer, which conceptually throws
> away the entire buffer and replaces it with what's on disk.  That it
> actually keeps portions of the buffer is an optimization, but the
> concept still stands.  So I don't see how it breaks the entire model,
> at least not in practice.

The optimization is beside the point: not calling b-c-f in some corner
case breaks the entire model because a user such as syntax-ppss relies
on b-c-f to know when to flush its cache, so if you don't call it when
the buffer is modified, the cache ends up stale.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-19 14:51   ` Phillip Lord
@ 2016-08-30  1:15     ` Stefan Monnier
  2016-08-30 14:34       ` Phillip Lord
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30  1:15 UTC (permalink / raw)
  To: emacs-devel

>  (or
>                 ;; previously this was not skewed if no region, but actually,
>                 ;; if there is no region we need to copy everything, we can
>                 ;; also do by declaring skew -- this is important for the
>                 ;; multi-lentic situation
>                 (not (or start stop length-before))
>                 ;; skews only occur in insertions which result in a positive
>                 ;; length-before. This also picks up no-insertion changes
>                 (and (< 0 length-before)
>                      ;; = start stop means we have a deletion because
>                      ;; there is no range after. Deletions seem to be
>                      ;; safe.
>                      (not (= start stop))))

I don't understand what this is doing.  It seems to be looking for
indirect clues rather than checking directly for the properties on which
the code relies.

Why not do something like:

    (defun lentic--b-c-f (start end)
      (setq-local lentic--b-c-pos (cons start end))
      ...)

    (defun lentic--a-c-f (start end length)
      (if (prog1 (not (and (eq start (car lentic--b-c-pos))
                           (eq (+ start length) (cdr lentic--b-c-pos))))
            (setq lentic--b-c-pos nil))
          ;; This a-c-f is not properly paired with the previous b-c-f.
          <do-the-skewed-thing>
        ;; Proper pairing
        <do-the-non-skew-thing>))

If the performance issue is serious enough, you can of course try to "do
it right" with something like:

    (defun lentic--b-c-f (start end)
      (setq-local lentic--b-c-data
                  (cons start (buffer-substring start end)))
      ...)

    (defun lentic--a-c-f (start end length)
      ;; Get the before-change content of start..end.
      (let ((old-text (substring (cdr lentic--b-c-data)
                                 (- start (car lentic--b-c-data))
                                 (- end length (car lentic--b-c-data)))))
        ;; Update lentic--b-c-data for possible subsequent other a-c-f calls.
        (setcdr lentic--b-c-data
                (concat (substring (cdr lentic--b-c-data)
                                   0 (- start (car lentic--b-c-data)))
                        (buffer-substring start end)
                        (substring (cdr lentic--b-c-data)
                                   (- end length (car lentic--b-c-data)))))
      <now-do-what-we-have-to-do>))

But it can admittedly be cumbersome since the old-text is now in a string
rather than being inside the buffer.

> 1) being able to know when b-c-f and a-c-f are not paired or consistent
> would be useful

Does the above lentic--b-c-pos give the needed info?

> 2) decreasing the number of times these occurs would be useful, even if
> it cannot be removed entirely.

Note that in the subst-char-in-region you could "make it pairup"
yourself by hand: if you have (< (+ start length) (cdr lentic--b-c-pos)),
then you can just

    (let ((diff (- (cdr lentic--b-c-pos) (+ start length))))
      (cl-incf length diff)
      (cl-incf end diff))

such that (eq (+ start length) (cdr lentic--b-c-pos)).


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30  0:25                                                                                   ` Stefan Monnier
@ 2016-08-30  2:26                                                                                     ` Daniel Colascione
  2016-08-30  2:38                                                                                     ` Eli Zaretskii
  1 sibling, 0 replies; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30  2:26 UTC (permalink / raw)
  To: Stefan Monnier, Eli Zaretskii; +Cc: emacs-devel



On 08/29/2016 05:25 PM, Stefan Monnier wrote:
>> So, while I agreed that #1 should probably be fixed, and even
>> suggested how to do that in the least risky way, actually doing that
>> is not a priority, IMO, not until we have a very grave problem caused
>> by it.
>
> FWIW, I think it's important to fix the insert-file-contents case.
> It breaks syntax-ppss, for example, although for various reasons of how
> syntax-ppss is implemented and used, this happens to rarely show up.
> [ So, yes, it's not top priority, but it should still be fixed.  ]

Agreed.

>
>>> #1 breaks the entire b-c-f model --- "hey, I'm about to modify the
>>> buffer, so throw away caches" ---- and can lead to anything with a
>>> cache flush in b-c-f (like syntax-ppss) not properly discarding
>>> out-of-date buffer information.
>> That single case of #1 is revert-buffer, which conceptually throws
>> away the entire buffer and replaces it with what's on disk.  That it
>> actually keeps portions of the buffer is an optimization, but the
>> concept still stands.  So I don't see how it breaks the entire model,
>> at least not in practice.
>
> The optimization is beside the point: not calling b-c-f in some corner
> case breaks the entire model because a user such as syntax-ppss relies
> on b-c-f to know when to flush its cache, so if you don't call it when
> the buffer is modified, the cache ends up stale.
>

Yes. That's what I meant. If you don't do this, b-c-f becomes 
practically useless.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 18:16                                                                                   ` Eli Zaretskii
@ 2016-08-30  2:27                                                                                     ` Daniel Colascione
  2016-08-30  2:44                                                                                       ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30  2:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: monnier, emacs-devel

On 08/29/2016 11:16 AM, Eli Zaretskii wrote:
>> Date: Mon, 29 Aug 2016 21:04:42 +0300
>> From: Eli Zaretskii <eliz@gnu.org>
>> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
>>
>> That single case of #1 is revert-buffer
>
> Btw: not every call to revert-buffer hits this case.  Quite the
> contrary: almost none of them do.  IOW, the situation where the
> before-change hook is not called at all is very rare even if you only
> consider the uses of revert-buffer.

I think we fundamentally disagree about how rarity affects bug important:

You: "This bug is rare. Cool. We don't have to worry about it much."
Me: "This bug is rare. That's awful. That means that people won't hit 
this bug until it causes some horrible, non-reproducible problem."



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30  0:25                                                                                   ` Stefan Monnier
  2016-08-30  2:26                                                                                     ` Daniel Colascione
@ 2016-08-30  2:38                                                                                     ` Eli Zaretskii
  2016-08-30  2:54                                                                                       ` Daniel Colascione
  2016-08-30 12:56                                                                                       ` Stefan Monnier
  1 sibling, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30  2:38 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: dancol, emacs-devel

> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> Cc: Daniel Colascione <dancol@dancol.org>, emacs-devel@gnu.org
> Date: Mon, 29 Aug 2016 20:25:06 -0400
> 
> >> #1 breaks the entire b-c-f model --- "hey, I'm about to modify the
> >> buffer, so throw away caches" ---- and can lead to anything with a
> >> cache flush in b-c-f (like syntax-ppss) not properly discarding
> >> out-of-date buffer information.
> > That single case of #1 is revert-buffer, which conceptually throws
> > away the entire buffer and replaces it with what's on disk.  That it
> > actually keeps portions of the buffer is an optimization, but the
> > concept still stands.  So I don't see how it breaks the entire model,
> > at least not in practice.
> 
> The optimization is beside the point: not calling b-c-f in some corner
> case breaks the entire model because a user such as syntax-ppss relies
> on b-c-f to know when to flush its cache, so if you don't call it when
> the buffer is modified, the cache ends up stale.

I'm saying that flushing the entire cache in that case is not a
problem, it's what needs to be done anyway.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30  2:27                                                                                     ` Daniel Colascione
@ 2016-08-30  2:44                                                                                       ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30  2:44 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: monnier, emacs-devel

> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Mon, 29 Aug 2016 19:27:37 -0700
> 
> I think we fundamentally disagree about how rarity affects bug important:

We've seen such fundamental disagreements before, so it's nothing new.

> You: "This bug is rare. Cool. We don't have to worry about it much."
> Me: "This bug is rare. That's awful. That means that people won't hit 
> this bug until it causes some horrible, non-reproducible problem."

When the fix is risky and touches code that affects almost everything
in Emacs, my method is much less likely to break important
functionality for the benefit of rare cases that can be worked around
or solved elsewhere.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30  2:38                                                                                     ` Eli Zaretskii
@ 2016-08-30  2:54                                                                                       ` Daniel Colascione
  2016-08-30 14:20                                                                                         ` Phillip Lord
  2016-08-30 15:08                                                                                         ` Eli Zaretskii
  2016-08-30 12:56                                                                                       ` Stefan Monnier
  1 sibling, 2 replies; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30  2:54 UTC (permalink / raw)
  To: Eli Zaretskii, Stefan Monnier; +Cc: emacs-devel

On 08/29/2016 07:38 PM, Eli Zaretskii wrote:
>> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
>> Cc: Daniel Colascione <dancol@dancol.org>, emacs-devel@gnu.org
>> Date: Mon, 29 Aug 2016 20:25:06 -0400
>>
>>>> #1 breaks the entire b-c-f model --- "hey, I'm about to modify the
>>>> buffer, so throw away caches" ---- and can lead to anything with a
>>>> cache flush in b-c-f (like syntax-ppss) not properly discarding
>>>> out-of-date buffer information.
>>> That single case of #1 is revert-buffer, which conceptually throws
>>> away the entire buffer and replaces it with what's on disk.  That it
>>> actually keeps portions of the buffer is an optimization, but the
>>> concept still stands.  So I don't see how it breaks the entire model,
>>> at least not in practice.
>>
>> The optimization is beside the point: not calling b-c-f in some corner
>> case breaks the entire model because a user such as syntax-ppss relies
>> on b-c-f to know when to flush its cache, so if you don't call it when
>> the buffer is modified, the cache ends up stale.
>
> I'm saying that flushing the entire cache in that case is not a
> problem, it's what needs to be done anyway.

How is a mode supposed to know that it's supposed to flush its cache?



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30  2:38                                                                                     ` Eli Zaretskii
  2016-08-30  2:54                                                                                       ` Daniel Colascione
@ 2016-08-30 12:56                                                                                       ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 12:56 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: dancol, emacs-devel

>> The optimization is beside the point: not calling b-c-f in some corner
>> case breaks the entire model because a user such as syntax-ppss relies
>> on b-c-f to know when to flush its cache, so if you don't call it when
>> the buffer is modified, the cache ends up stale.
> I'm saying that flushing the entire cache in that case is not a
> problem, it's what needs to be done anyway.

The problem is that b-c-f is not called at all, so syntax-ppss doesn't
know that it should flush (any part of) its cache.
Calling b-c-f on point-min...point-max would be perfectly fine, indeed.
But currently b-c-f is not called at all.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-28 11:23                                                       ` Daniel Colascione
  2016-08-28 15:01                                                         ` Stefan Monnier
  2016-08-28 22:36                                                         ` Stefan Monnier
@ 2016-08-30 13:30                                                         ` Phillip Lord
  2016-08-30 13:39                                                           ` Stefan Monnier
  2016-08-30 15:47                                                           ` Eli Zaretskii
  2 siblings, 2 replies; 189+ messages in thread
From: Phillip Lord @ 2016-08-30 13:30 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Alan Mackenzie, Stefan Monnier, emacs-devel

Daniel Colascione <dancol@dancol.org> writes:

>> As mentioned in my so-called "hand-waving", any details you may need can
>> be stored somewhere for use.
>
> Is it really better to force that complexity (which, in the limit, amounts to
> full shadow buffers) onto mode authors instead of changing Emacs to balance
> b-c-f with a-c-f 100% of the time instead of 99%?


I think to really avoid the complexity for mode authors, b-c-f and a-c-f
need to not only balance, but also to be consistent. At the moment, they
are not that either -- they can signal different locations for a given
change.

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 13:30                                                         ` Phillip Lord
@ 2016-08-30 13:39                                                           ` Stefan Monnier
  2016-08-31 11:04                                                             ` Phillip Lord
  2016-08-30 15:47                                                           ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 13:39 UTC (permalink / raw)
  To: emacs-devel

> I think to really avoid the complexity for mode authors, b-c-f and a-c-f
> need to not only balance, but also to be consistent. At the moment, they
> are not that either -- they can signal different locations for a given
> change.

I think "balanced + a guarantee that a-c-f covers a subset of b-c-f" is
sufficient, since you can then trivially extend a-c-f's subset to the
corresponding "identical" locations if you need it.

AFAIK we do have the "a-c-f covers a subset of b-c-f" property,
right now (modulo bugs, of course).


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 15:44                                                                         ` Stefan Monnier
@ 2016-08-30 14:07                                                                           ` Phillip Lord
  2016-08-30 15:51                                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Phillip Lord @ 2016-08-30 14:07 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Daniel Colascione, emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>>> I guess a way to "fix" it would be to add a random fudge factor to the
>>> b-c-f calls, plus add random dummy calls to b-c-f, and sprinkle the
>>> lisp/*.el code with combine-after-change-calls.  This way, the "properly
>>> paired up" case will be much more exceptional.
>> You can't be serious.
>
> If it can finally get us rid of people who insist they want exactly
> paired/matched/symmetric b/a-c-f, then I'd willing to do that, yes.
>
> AFAICT the result would be simpler, cleaner, and more robust code, since
> instead of trying to think of the various different ways a buffer can
> change here or there, the coder would be forced to step back and think
> how to handle the general case.


I use these functions for my package lentic, and I do handle the general
case.

In fact, I started off by handling the general case -- this involves
using a-c-f only and just ignoring the parameters. It works, of course,
but it is inefficient enough that it limits the usability to small
buffers.

So, I made use of the information on a-c-f and b-c-f. This increases the
code complexity significantly, but it reduces the load massively. That
b-c-f and a-c-f are not always balanced or consistent, unfortunately,
works directly against this aim.

So having them balanced and consistent would be nice. I agree that in
fixing this, bad things might happens. But surely that is a risk of
fiddling with any core part of Emacs. One response would be to not to
it. Another response would be to incrementally increase the number of
test cases Emacs has to enable this (and other) changes in the core to
be made with more confidence.

Phil




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 14:50                                                                     ` Eli Zaretskii
  2016-08-29 15:30                                                                       ` Daniel Colascione
@ 2016-08-30 14:12                                                                       ` Phillip Lord
  2016-08-30 16:06                                                                         ` Eli Zaretskii
  2016-08-30 17:12                                                                       ` Alan Mackenzie
  2016-09-01 21:25                                                                       ` Davis Herring
  3 siblings, 1 reply; 189+ messages in thread
From: Phillip Lord @ 2016-08-30 14:12 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Daniel Colascione, monnier, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:
>> Sure, I guess you could argue that current Emacs behavior is consistent with
>> the manual, but it's not what anyone would reasonably expect, and the
>> current behavior is surprising even to people who have been writing elisp
>> for a long time.
>
> Surprising or not, the existing implementation is in use for many
> years, and until now no complaints were presented about it.

Actually, it caused me significant issues several years ago, and I would
have prefered that the hooks were balanced. I'd rather fix things than
complain, but you can consider this a complaint if you will.

> And even now we have a single complaint from a single use case of a
> single package (which meanwhile fixed the problem without any core
> changes). Which is ample evidence that the existing implementation
> does a good job after all.

No, I don't think it is. It might be evidence that people know to seek
alternative solutions instead of using b-c-f and a-c-f.


>> I'm confident that with enough review, the core code could be changed to
>> make b-c-f and a-c-f symmetric without causing weird bugs elsewhere. The
>> necessary refactoring will probably make the logic cleaner as well.
>> 
>> Of course there's a risk that changing b-c-f will itself produce weird side
>> effects, but I have a hard time seeing how any code could actually depend on
>> the current surprising behavior.
>
> That's exactly the nonchalant attitude towards changes in core that
> explains why, after 30-odd years of development, which should have
> given us an asymptotically more and more stable Emacs, we still
> succeed quite regularly to break core code and basic features, while
> "confidently" relying on our mythical abilities to refactor correctly
> without any serious testing coverage.  Never again.

Can I deliberately misinterpret this as saying that you think that the
changes would be fine so long as we add lots of tests at the same time?

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30  2:54                                                                                       ` Daniel Colascione
@ 2016-08-30 14:20                                                                                         ` Phillip Lord
  2016-08-30 15:08                                                                                         ` Eli Zaretskii
  1 sibling, 0 replies; 189+ messages in thread
From: Phillip Lord @ 2016-08-30 14:20 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Eli Zaretskii, Stefan Monnier, emacs-devel

Daniel Colascione <dancol@dancol.org> writes:

> On 08/29/2016 07:38 PM, Eli Zaretskii wrote:
>> I'm saying that flushing the entire cache in that case is not a
>> problem, it's what needs to be done anyway.
>
> How is a mode supposed to know that it's supposed to flush its cache?


I don't know that either and it would be lovely to know when.

I've posted my heuristic earlier, which works for me but comes with no
guarantees at all.


https://lists.gnu.org/archive/html/emacs-devel/2016-08/msg00381.html



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-30  1:15     ` Stefan Monnier
@ 2016-08-30 14:34       ` Phillip Lord
  2016-08-30 15:11         ` Stefan Monnier
  2016-08-30 16:08         ` Eli Zaretskii
  0 siblings, 2 replies; 189+ messages in thread
From: Phillip Lord @ 2016-08-30 14:34 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>  (or
>>                 ;; previously this was not skewed if no region, but actually,
>>                 ;; if there is no region we need to copy everything, we can
>>                 ;; also do by declaring skew -- this is important for the
>>                 ;; multi-lentic situation
>>                 (not (or start stop length-before))
>>                 ;; skews only occur in insertions which result in a positive
>>                 ;; length-before. This also picks up no-insertion changes
>>                 (and (< 0 length-before)
>>                      ;; = start stop means we have a deletion because
>>                      ;; there is no range after. Deletions seem to be
>>                      ;; safe.
>>                      (not (= start stop))))
>
> I don't understand what this is doing.


That's a shame. I don't understand what it is doing either, and I was
hoping that you might do.


> It seems to be looking for indirect clues rather than checking
> directly for the properties on which the code relies.

Perhaps. At the moment, the only thing function that I know definately
causes me problems is subst-char-in-region.

> Why not do something like:
>
>     (defun lentic--b-c-f (start end)
>       (setq-local lentic--b-c-pos (cons start end))
>       ...)
>
>     (defun lentic--a-c-f (start end length)
>       (if (prog1 (not (and (eq start (car lentic--b-c-pos))
>                            (eq (+ start length) (cdr lentic--b-c-pos))))
>             (setq lentic--b-c-pos nil))
>           ;; This a-c-f is not properly paired with the previous b-c-f.
>           <do-the-skewed-thing>
>         ;; Proper pairing
>         <do-the-non-skew-thing>))

I will try and test this to see.


> If the performance issue is serious enough, you can of course try to "do
> it right" with something like:
>
>     (defun lentic--b-c-f (start end)
>       (setq-local lentic--b-c-data
>                   (cons start (buffer-substring start end)))
>       ...)
>
>     (defun lentic--a-c-f (start end length)
>       ;; Get the before-change content of start..end.
>       (let ((old-text (substring (cdr lentic--b-c-data)
>                                  (- start (car lentic--b-c-data))
>                                  (- end length (car lentic--b-c-data)))))
>         ;; Update lentic--b-c-data for possible subsequent other a-c-f calls.
>         (setcdr lentic--b-c-data
>                 (concat (substring (cdr lentic--b-c-data)
>                                    0 (- start (car lentic--b-c-data)))
>                         (buffer-substring start end)
>                         (substring (cdr lentic--b-c-data)
>                                    (- end length (car lentic--b-c-data)))))
>       <now-do-what-we-have-to-do>))
>
> But it can admittedly be cumbersome since the old-text is now in a string
> rather than being inside the buffer.

Because, I am not using the before and after positions just to recognise
the string that has changed. I am have to calculate the equivalent
positions in the other "lentic" buffer; and this can only be done before
the change, since the two buffers are them in a consistent state.

In the case that they are skewed, I have to throw all my knowledge away,
since the converted positions are not unreliable. So I copy the whole
buffer, and apply the general (unoptimized) transformation.

>> 1) being able to know when b-c-f and a-c-f are not paired or consistent
>> would be useful
>
> Does the above lentic--b-c-pos give the needed info?
>
>> 2) decreasing the number of times these occurs would be useful, even if
>> it cannot be removed entirely.
>
> Note that in the subst-char-in-region you could "make it pairup"
> yourself by hand: if you have (< (+ start length) (cdr lentic--b-c-pos)),
> then you can just
>
>     (let ((diff (- (cdr lentic--b-c-pos) (+ start length))))
>       (cl-incf length diff)
>       (cl-incf end diff))
>
> such that (eq (+ start length) (cdr lentic--b-c-pos)).


So, this works because subst-char-in-region is guaranteed not to change
the size of the region right? But, how do I know that
subst-char-in-region has been called? I discovered this problem first,
when fill-paragraph broke lentic. It just so happens that
subst-char-in-region was the culprit; it wasn't the command though.

Phil




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30  2:54                                                                                       ` Daniel Colascione
  2016-08-30 14:20                                                                                         ` Phillip Lord
@ 2016-08-30 15:08                                                                                         ` Eli Zaretskii
  1 sibling, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 15:08 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: monnier, emacs-devel

> Cc: emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Mon, 29 Aug 2016 19:54:52 -0700
> 
> On 08/29/2016 07:38 PM, Eli Zaretskii wrote:
> >> From: Stefan Monnier <monnier@IRO.UMontreal.CA>
> >> Cc: Daniel Colascione <dancol@dancol.org>, emacs-devel@gnu.org
> >> Date: Mon, 29 Aug 2016 20:25:06 -0400
> >>
> >>>> #1 breaks the entire b-c-f model --- "hey, I'm about to modify the
> >>>> buffer, so throw away caches" ---- and can lead to anything with a
> >>>> cache flush in b-c-f (like syntax-ppss) not properly discarding
> >>>> out-of-date buffer information.
> >>> That single case of #1 is revert-buffer, which conceptually throws
> >>> away the entire buffer and replaces it with what's on disk.  That it
> >>> actually keeps portions of the buffer is an optimization, but the
> >>> concept still stands.  So I don't see how it breaks the entire model,
> >>> at least not in practice.
> >>
> >> The optimization is beside the point: not calling b-c-f in some corner
> >> case breaks the entire model because a user such as syntax-ppss relies
> >> on b-c-f to know when to flush its cache, so if you don't call it when
> >> the buffer is modified, the cache ends up stale.
> >
> > I'm saying that flushing the entire cache in that case is not a
> > problem, it's what needs to be done anyway.
> 
> How is a mode supposed to know that it's supposed to flush its cache?

I think I misunderstood you, sorry.  I thought you were saying that in
the absence of the before-change call a mode will decide to flush its
caches, and that you've considered such flushing a problem of some
sort.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-30 14:34       ` Phillip Lord
@ 2016-08-30 15:11         ` Stefan Monnier
  2016-08-31 11:00           ` Phillip Lord
  2016-09-01  6:40           ` Phillip Lord
  2016-08-30 16:08         ` Eli Zaretskii
  1 sibling, 2 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 15:11 UTC (permalink / raw)
  To: emacs-devel

>> But it can admittedly be cumbersome since the old-text is now in a string
>> rather than being inside the buffer.
> Because, I am not using the before and after positions just to recognise
> the string that has changed.

I was not suggesting to use those position to recognize the string:
I was suggesting to use the suggested code to get the old-string so that
you can then do what you need on the "before change" state.

> I am have to calculate the equivalent positions in the other "lentic"
> buffer; and this can only be done before the change, since the two
> buffers are them in a consistent state.

The idea is that my suggested code gives you the needed info.
More specifically, the other buffer is (well, should be) in a state
consistent with "the current buffer where start..end is replaced (back)
with `old-text'".

So that should give you the info needed to update things without doing
a "complete flush".  As mentioned, it may be inconvenient to use it
(depending on details of how the rest of the code is implemented) since
the old-text is now in a string rather than being right there in
the buffer.

>> Note that in the subst-char-in-region you could "make it pairup"
>> yourself by hand: if you have (< (+ start length) (cdr lentic--b-c-pos)),
>> then you can just
>> 
>>     (let ((diff (- (cdr lentic--b-c-pos) (+ start length))))
>>     (cl-incf length diff)
>>     (cl-incf end diff))
>> 
>> such that (eq (+ start length) (cdr lentic--b-c-pos)).
> So, this works because subst-char-in-region is guaranteed not to change
> the size of the region right?

No.  It works because a-c-f's arguments say "nothing was changed before
START and after END", so it's always safe (conservative) to move START
towards BOB or move END towards EOB (of course, when updating END you
also need to update LENGTH correspondingly).


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 13:30                                                         ` Phillip Lord
  2016-08-30 13:39                                                           ` Stefan Monnier
@ 2016-08-30 15:47                                                           ` Eli Zaretskii
  2016-08-30 16:01                                                             ` Stefan Monnier
  2016-08-30 16:23                                                             ` Daniel Colascione
  1 sibling, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 15:47 UTC (permalink / raw)
  To: Phillip Lord; +Cc: acm, dancol, monnier, emacs-devel

> From: phillip.lord@russet.org.uk (Phillip Lord)
> Date: Tue, 30 Aug 2016 14:30:13 +0100
> Cc: Alan Mackenzie <acm@muc.de>, Stefan Monnier <monnier@IRO.UMontreal.CA>,
> 	emacs-devel@gnu.org
> 
> I think to really avoid the complexity for mode authors, b-c-f and a-c-f
> need to not only balance, but also to be consistent. At the moment, they
> are not that either -- they can signal different locations for a given
> change.

You are setting the bar impossibly high by expecting that.
Implementing what you want would need significant changes in how the
insdel functions are implemented and used.  In particular, some
complex changes will probably have to do things twice: once just to
figure out which changes are needed, the other time to actually do
that while calling the hooks in the way you want.  That's because in
some situations we discover the required changes as we go, and have no
idea in advance what we will find.

Read the code where these functions are called, and you will see what
I mean.

insert-file-contents as called by revert-buffer is a case in point: we
don't know which parts of the old text will need to be deleted until
we do the job by comparing the buffer with the file on disk; we delete
each portion as we discover it.

To keep this issue in its proper perspective, we have other hooks that
are similarly "inconsistent".  For example, window-scroll-functions
can be called by the display engine any number of times during a
single redisplay cycle, because the display engine many times plays
"catch and loose", trying something, then falling back to some backup
plan if plan A failed; but by the time it understands it needs to give
up on plane A, it already have called the hooks.

So I submit that this "inconsistency" is actually an inherent trait of
the Emacs hooks, at least some of them, and at this point the only way
to avoid that is completely rewrite the corresponding part(s) of the
internals.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 14:07                                                                           ` Phillip Lord
@ 2016-08-30 15:51                                                                             ` Eli Zaretskii
  2016-08-30 16:22                                                                               ` Daniel Colascione
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 15:51 UTC (permalink / raw)
  To: Phillip Lord; +Cc: dancol, monnier, emacs-devel

> From: phillip.lord@russet.org.uk (Phillip Lord)
> Date: Tue, 30 Aug 2016 15:07:27 +0100
> Cc: Daniel Colascione <dancol@dancol.org>, emacs-devel@gnu.org
> 
> So having them balanced and consistent would be nice. I agree that in
> fixing this, bad things might happens. But surely that is a risk of
> fiddling with any core part of Emacs. One response would be to not to
> it. Another response would be to incrementally increase the number of
> test cases Emacs has to enable this (and other) changes in the core to
> be made with more confidence.

My response is that we should not do it until we have decent test
coverage of the insdel functionality.  I simply don't believe in our
ability to avoid breakage in this core functionality unless we have
good test coverage.  Been there, done that, have bruises to prove it.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 15:47                                                           ` Eli Zaretskii
@ 2016-08-30 16:01                                                             ` Stefan Monnier
  2016-08-30 16:58                                                               ` Eli Zaretskii
  2016-08-30 16:23                                                             ` Daniel Colascione
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 16:01 UTC (permalink / raw)
  To: emacs-devel

> You are setting the bar impossibly high by expecting that.
> Implementing what you want would need significant changes in how the
> insdel functions are implemented and used.  In particular, some
> complex changes will probably have to do things twice: once just to
> figure out which changes are needed, the other time to actually do
> that while calling the hooks in the way you want.  That's because in
> some situations we discover the required changes as we go, and have no
> idea in advance what we will find.

Actually, we do have some idea beforehand, as evidenced by the fact that
we call b-c-f with valid data.  It's just that after the fact we have
a more precise knowledge of what has actually been changed, so a-c-f can
give more precise bounds.

But as mentioned in some other message, the a-c-f function can itself
extend its arguments to match those of the b-c-f if it needs them to
be matched.

We could also change the C code to perform this "extension" of the
region passed to a-c-f so that the b-c-f region and the a-c-f region
match, but that would make the region passed to a-c-f less precise, so
those users of a-c-f which don't care about the pairing (the majority of
the users) would be penalized (tho they'd still work correctly: just
suboptimally) since there's no way for them to recover the
tighter region.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 14:12                                                                       ` Phillip Lord
@ 2016-08-30 16:06                                                                         ` Eli Zaretskii
  2016-08-31 11:20                                                                           ` Phillip Lord
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 16:06 UTC (permalink / raw)
  To: Phillip Lord; +Cc: dancol, monnier, emacs-devel

> From: phillip.lord@russet.org.uk (Phillip Lord)
> Cc: Daniel Colascione <dancol@dancol.org>,  monnier@iro.umontreal.ca,  emacs-devel@gnu.org
> Date: Tue, 30 Aug 2016 15:12:13 +0100
> 
> > Surprising or not, the existing implementation is in use for many
> > years, and until now no complaints were presented about it.
> 
> Actually, it caused me significant issues several years ago, and I would
> have prefered that the hooks were balanced.

Me too, believe it or not.  But this is not about our preferences.
This is about the tough choices we must make when faced with the
current situation, where this code was working for many years, we have
a very small number of people who even understand the intricacies of
the implementation, and users certainly don't expect to see Emacs 26
have bugs in basic text handling in buffers.

IOW, we need to find the lesser evil.

> > And even now we have a single complaint from a single use case of a
> > single package (which meanwhile fixed the problem without any core
> > changes). Which is ample evidence that the existing implementation
> > does a good job after all.
> 
> No, I don't think it is. It might be evidence that people know to seek
> alternative solutions instead of using b-c-f and a-c-f.

Fine with me.  I indeed prefer that in the current situation any bugs
this could cause be fixed or worked around in the packages that are
hit by them.  As long as these problems are rare and far between, that
is better than risking to break insdel and its callers, which could be
virtually anywhere.

If someone refactors insdel to introduce some significant new feature,
then instability can be justified.  But otherwise, it sounds nuts to
me to risk that, given the rarity of the problems and the ability of
the packages to work around them.  Especially, as we have no way
whatsoever of verifying the changes by tests.

> > That's exactly the nonchalant attitude towards changes in core that
> > explains why, after 30-odd years of development, which should have
> > given us an asymptotically more and more stable Emacs, we still
> > succeed quite regularly to break core code and basic features, while
> > "confidently" relying on our mythical abilities to refactor correctly
> > without any serious testing coverage.  Never again.
> 
> Can I deliberately misinterpret this as saying that you think that the
> changes would be fine so long as we add lots of tests at the same time?

Not "at the same time", but "as a prerequisite" for any serious
consideration of such changes.  IOW, I want to see the tests first,
decide whether I like their degree of coverage, and only then I will
be prepared to _talk_ about any changes in this area.  And the first
step in that talk will have to be someone presenting a rather complete
design of the changes, including an analysis of the current callers
and how each one (or each class) of them will work under the new
design.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-30 14:34       ` Phillip Lord
  2016-08-30 15:11         ` Stefan Monnier
@ 2016-08-30 16:08         ` Eli Zaretskii
  1 sibling, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 16:08 UTC (permalink / raw)
  To: Phillip Lord; +Cc: monnier, emacs-devel

> From: phillip.lord@russet.org.uk (Phillip Lord)
> Date: Tue, 30 Aug 2016 15:34:19 +0100
> Cc: emacs-devel@gnu.org
> 
> So, this works because subst-char-in-region is guaranteed not to change
> the size of the region right?

Caution: in characters, but not necessarily in bytes!



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 15:51                                                                             ` Eli Zaretskii
@ 2016-08-30 16:22                                                                               ` Daniel Colascione
  2016-08-30 16:46                                                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 16:22 UTC (permalink / raw)
  To: Eli Zaretskii, Phillip Lord; +Cc: monnier, emacs-devel

On 08/30/2016 08:51 AM, Eli Zaretskii wrote:
>> From: phillip.lord@russet.org.uk (Phillip Lord)
>> Date: Tue, 30 Aug 2016 15:07:27 +0100
>> Cc: Daniel Colascione <dancol@dancol.org>, emacs-devel@gnu.org
>>
>> So having them balanced and consistent would be nice. I agree that in
>> fixing this, bad things might happens. But surely that is a risk of
>> fiddling with any core part of Emacs. One response would be to not to
>> it. Another response would be to incrementally increase the number of
>> test cases Emacs has to enable this (and other) changes in the core to
>> be made with more confidence.
>
> My response is that we should not do it until we have decent test
> coverage of the insdel functionality.  I simply don't believe in our
> ability to avoid breakage in this core functionality unless we have
> good test coverage.  Been there, done that, have bruises to prove it.

More tests in general would be nice. I have no objection to requiring 
test coverage for insdel before making major changes; my objection is to 
a blanket ban on changes even *with* test coverage. I was the under the 
impression that your preference was for the latter model, but IIUC, you 
actually hold the former position.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 15:47                                                           ` Eli Zaretskii
  2016-08-30 16:01                                                             ` Stefan Monnier
@ 2016-08-30 16:23                                                             ` Daniel Colascione
  2016-08-30 16:53                                                               ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 16:23 UTC (permalink / raw)
  To: Eli Zaretskii, Phillip Lord; +Cc: acm, monnier, emacs-devel



On 08/30/2016 08:47 AM, Eli Zaretskii wrote:
>> From: phillip.lord@russet.org.uk (Phillip Lord)
>> Date: Tue, 30 Aug 2016 14:30:13 +0100
>> Cc: Alan Mackenzie <acm@muc.de>, Stefan Monnier <monnier@IRO.UMontreal.CA>,
>> 	emacs-devel@gnu.org
>>
>> I think to really avoid the complexity for mode authors, b-c-f and a-c-f
>> need to not only balance, but also to be consistent. At the moment, they
>> are not that either -- they can signal different locations for a given
>> change.
>
> You are setting the bar impossibly high by expecting that.

To be fair, according to Alan, XEmacs meets this impossibly high bar. 
(And its insdel is considerably simpler.)

In today's world, do we really *need* the optimizations that complicate 
change region tracking? Might these things just be just as unnecessary 
as the old code that used to special-case self-insert-command in the 
event loop?



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 16:22                                                                               ` Daniel Colascione
@ 2016-08-30 16:46                                                                                 ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 16:46 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: emacs-devel, monnier, phillip.lord

> Cc: monnier@IRO.UMontreal.CA, emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Tue, 30 Aug 2016 09:22:21 -0700
> 
> > My response is that we should not do it until we have decent test
> > coverage of the insdel functionality.  I simply don't believe in our
> > ability to avoid breakage in this core functionality unless we have
> > good test coverage.  Been there, done that, have bruises to prove it.
> 
> More tests in general would be nice. I have no objection to requiring 
> test coverage for insdel before making major changes; my objection is to 
> a blanket ban on changes even *with* test coverage. I was the under the 
> impression that your preference was for the latter model, but IIUC, you 
> actually hold the former position.

I'm simply disillusioned wrt to possibility of any significant
progress in having tests in these areas.  Almost all of our tests are
in application areas, while the functions in src/ remain almost
completely uncovered.  I have no reason to believe this will change
any time soon (but I will be happy to be mistaken, of course).

That is why I could have sent ambiguous messages in this regard.

(And it's not only insdel that will be affected, because
signal_before_change and signal_after_change also affect the various
caches we maintain for a buffer, its markers, text properties and
overlays, etc.  All of which will have to be covered by tests, before
we can consider serious changes in this area.)



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 16:23                                                             ` Daniel Colascione
@ 2016-08-30 16:53                                                               ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 16:53 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: acm, emacs-devel, monnier, phillip.lord

> Cc: acm@muc.de, monnier@IRO.UMontreal.CA, emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Tue, 30 Aug 2016 09:23:51 -0700
> 
> > You are setting the bar impossibly high by expecting that.
> 
> To be fair, according to Alan, XEmacs meets this impossibly high bar. 

I disagree with Alan (having looked at XEmacs' sources).

> (And its insdel is considerably simpler.)

That wasn't my impression.  Beyond some stuff that is missing simply
because XEmacs doesn't support it, the code is the same, except that
they also have a separate "multi-change" hook called around changes
that are done piecemeal, in addition to the hooks we have.  IOW, it's
a different model, and not necessarily a solution that we are looking
for.

Of course, I didn't read their sources too seriously, so maybe I
missed something.

> In today's world, do we really *need* the optimizations that complicate 
> change region tracking? Might these things just be just as unnecessary 
> as the old code that used to special-case self-insert-command in the 
> event loop?

I'm not sure which optimizations are you talking about, so it's hard
to answer that question.  I can tell that decoding a large file when
we visit it takes a significant amount of time, even with today's
machines.  So at least some optimizations we have, like reading into
the gap, are probably still justified.

Of course, removing/simplifying optimizations in these internals would
also need good test coverage, to make sure we don't introduce bugs
while at that ;-)



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 16:01                                                             ` Stefan Monnier
@ 2016-08-30 16:58                                                               ` Eli Zaretskii
  2016-08-30 17:57                                                                 ` Stefan Monnier
  2016-08-31 11:12                                                                 ` Phillip Lord
  0 siblings, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 16:58 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Tue, 30 Aug 2016 12:01:22 -0400
> 
> > You are setting the bar impossibly high by expecting that.
> > Implementing what you want would need significant changes in how the
> > insdel functions are implemented and used.  In particular, some
> > complex changes will probably have to do things twice: once just to
> > figure out which changes are needed, the other time to actually do
> > that while calling the hooks in the way you want.  That's because in
> > some situations we discover the required changes as we go, and have no
> > idea in advance what we will find.
> 
> Actually, we do have some idea beforehand, as evidenced by the fact that
> we call b-c-f with valid data.  It's just that after the fact we have
> a more precise knowledge of what has actually been changed, so a-c-f can
> give more precise bounds.

I was under the impression that Phillip wanted the data be accurate,
not just valid.  Because if validity is the only requirement, we could
always call the before-change hook with the limits of the entire
buffer, and be done.  Clearly, that would not be very useful, to say
the least.

> We could also change the C code to perform this "extension" of the
> region passed to a-c-f so that the b-c-f region and the a-c-f region
> match, but that would make the region passed to a-c-f less precise, so
> those users of a-c-f which don't care about the pairing (the majority of
> the users) would be penalized (tho they'd still work correctly: just
> suboptimally) since there's no way for them to recover the
> tighter region.

Right.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 14:50                                                                     ` Eli Zaretskii
  2016-08-29 15:30                                                                       ` Daniel Colascione
  2016-08-30 14:12                                                                       ` Phillip Lord
@ 2016-08-30 17:12                                                                       ` Alan Mackenzie
  2016-08-30 17:27                                                                         ` Daniel Colascione
  2016-08-30 17:27                                                                         ` Eli Zaretskii
  2016-09-01 21:25                                                                       ` Davis Herring
  3 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 17:12 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Daniel Colascione, monnier, emacs-devel

Hello, Eli.

On Mon, Aug 29, 2016 at 05:50:11PM +0300, Eli Zaretskii wrote:
> > From: Daniel Colascione <dancol@dancol.org>
> > Date: Sun, 28 Aug 2016 20:18:32 -0700

> >     Please trust me that the documentation misleads.

> You are welcome to suggest more accurate wording that describes the
> current implementation.

I think it's only fair to point out that I did precisly this almost
three weeks ago (on 2016-08-10) and the welcome my efforts got was
somewhat less than wholeheartedly warm.

The current documentation misleads in asserting that b-c-f and a-c-f
cannot be used together in balanced pairs.  They most assuredly can,
with the exception of a tiny number of rarely occurring cases.  If this
were not true, CC Mode would not work at all.

Using b-c-f and a-c-f together is an essential technique - there are
things that cannot be done without it, or at least not in any reasonable
manner.  In this sense, maintaining a duplicate shadow buffer, or
scanning from BOB at every buffer change, or maintaining a separate
record of all text properties on a buffer, don't fall into the category
of reasonable, from my point of view.

Eliminating this technique from Emacs, whether by "polluting" the source
to stop it working altogether (as suggested by Stefan), or by forbidding
it in the documentation, has the effect of making Emacs a less powerful
programming system.  I don't think this is what any of us should want.

[ .... ]

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:12                                                                       ` Alan Mackenzie
@ 2016-08-30 17:27                                                                         ` Daniel Colascione
  2016-08-30 17:42                                                                           ` Eli Zaretskii
  2016-08-30 18:00                                                                           ` Stefan Monnier
  2016-08-30 17:27                                                                         ` Eli Zaretskii
  1 sibling, 2 replies; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 17:27 UTC (permalink / raw)
  To: Alan Mackenzie, Eli Zaretskii; +Cc: monnier, emacs-devel

On 08/30/2016 10:12 AM, Alan Mackenzie wrote:
> Hello, Eli.
>
> On Mon, Aug 29, 2016 at 05:50:11PM +0300, Eli Zaretskii wrote:
>>> From: Daniel Colascione <dancol@dancol.org>
>>> Date: Sun, 28 Aug 2016 20:18:32 -0700
>
>>>     Please trust me that the documentation misleads.
>
>> You are welcome to suggest more accurate wording that describes the
>> current implementation.
>
> I think it's only fair to point out that I did precisly this almost
> three weeks ago (on 2016-08-10) and the welcome my efforts got was
> somewhat less than wholeheartedly warm.
>
> The current documentation misleads in asserting that b-c-f and a-c-f
> cannot be used together in balanced pairs.  They most assuredly can,
> with the exception of a tiny number of rarely occurring cases.  If this
> were not true, CC Mode would not work at all.
>
> Using b-c-f and a-c-f together is an essential technique - there are
> things that cannot be done without it, or at least not in any reasonable
> manner.  In this sense, maintaining a duplicate shadow buffer, or
> scanning from BOB at every buffer change, or maintaining a separate
> record of all text properties on a buffer, don't fall into the category
> of reasonable, from my point of view.
>
> Eliminating this technique from Emacs, whether by "polluting" the source
> to stop it working altogether (as suggested by Stefan), or by forbidding
> it in the documentation, has the effect of making Emacs a less powerful
> programming system.  I don't think this is what any of us should want.
>
> [ .... ]

How about this? I think this revised text captures the intent of the 
current implementation and preserves the ability to use b-c-f and a-c-f 
together. (The current revert-buffer behavior is just a bug and is 
contrary to my proposed documentation.)

diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 213eec9..6511da8 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -4798,6 +4798,13 @@ Change Hooks
  has been changed is always the current buffer when the function is
  called.

+The region given to each of these functions is a conservative
+approximation of the region about to changed.  After running the
+before-change-functions, Emacs will make zero or more fine-grained
+buffer changes and run after-change-functions for each.  Do not expect
+before-change-functions and after-change-functions to be called in
+balanced pairs.
+
  The length of the old text is the difference between the buffer
  positions before and after that text as it was before the change.  As
  for the changed text, its length is simply the difference between the
@@ -4809,14 +4816,14 @@ Change Hooks
  as changes in buffers created by Emacs internally for certain jobs,
  that should not be visible to Lisp programs.

-  Do @emph{not} expect the before-change hooks and the after-change
-hooks be called in balanced pairs around each buffer change.  Also
-don't expect the before-change hooks to be called for every chunk of
-text Emacs is about to delete.  These hooks are provided on the
-assumption that Lisp programs will use either before- or the
-after-change hooks, but not both, and the boundaries of the region
-where the changes happen might include more than just the actual
-changed text, or even lump together several changes done piecemeal.
+   Do @emph{not} expect the before-change hooks and the after-change
+hooks be called in balanced pairs around each buffer change.
+The before-change-functions region is a conservative bound on the zero
+or more fine-grained changes to follow.  Emacs informs user code about
+the actual changes to the buffer through calls to
+after-change-functions; these fine-grained changes will always fall
+inside the broad change region Emacs describes by calling
+before-change-functions.

  @defmac combine-after-change-calls body@dots{}
  The macro executes @var{body} normally, but arranges to call the
diff --git a/src/buffer.c b/src/buffer.c
index 24c997f..60e448f 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -6027,6 +6027,13 @@ the beginning and end of the range of old text to 
be changed.
  \(For an insertion, the beginning and end are at the same place.)
  No information is given about the length of the text after the change.

+The region given to each of these functions is a conservative
+approximation of the region about to changed.  After running the
+before-change-functions, Emacs will make zero or more fine-grained
+buffer changes and run `after-change-functions' for each.  Do not
+expect `before-change-functions' and `after-change-functions' to be
+called in balanced pairs.
+
  Buffer changes made while executing the `before-change-functions'
  don't call any before-change or after-change functions.
  That's because `inhibit-modification-hooks' is temporarily set non-nil.



^ permalink raw reply related	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:12                                                                       ` Alan Mackenzie
  2016-08-30 17:27                                                                         ` Daniel Colascione
@ 2016-08-30 17:27                                                                         ` Eli Zaretskii
  2016-08-30 17:42                                                                           ` Alan Mackenzie
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 17:27 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: dancol, monnier, emacs-devel

> Date: Tue, 30 Aug 2016 17:12:22 +0000
> Cc: Daniel Colascione <dancol@dancol.org>, monnier@iro.umontreal.ca,
>   emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > You are welcome to suggest more accurate wording that describes the
> > current implementation.
> 
> I think it's only fair to point out that I did precisly this almost
> three weeks ago (on 2016-08-10) and the welcome my efforts got was
> somewhat less than wholeheartedly warm.

Your attempt didn't describe the current implementation.  It described
what you thought it should be.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:27                                                                         ` Eli Zaretskii
@ 2016-08-30 17:42                                                                           ` Alan Mackenzie
  2016-08-30 17:53                                                                             ` Eli Zaretskii
  2016-08-30 18:14                                                                             ` Stefan Monnier
  0 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 17:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: dancol, monnier, emacs-devel

Hello, Eli.

On Tue, Aug 30, 2016 at 08:27:48PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 30 Aug 2016 17:12:22 +0000
> > Cc: Daniel Colascione <dancol@dancol.org>, monnier@iro.umontreal.ca,
> >   emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > > You are welcome to suggest more accurate wording that describes the
> > > current implementation.

> > I think it's only fair to point out that I did precisly this almost
> > three weeks ago (on 2016-08-10) and the welcome my efforts got was
> > somewhat less than wholeheartedly warm.

> Your attempt didn't describe the current implementation.  It described
> what you thought it should be.

The text in question (intended for the Elisp manual) was:

  Normally the before-change-functions and the after-change-functions
  hooks are called in balanced pairs around each buffer change, enabling
  state to be determined in a before-change function and used in an
  after-change function.  However on rare occasions,
  before-change-functions is not called before a buffer change and
  after-change-functions is thus called twice in succession.  Your
  program should be ready to deal with such an occurrence.

The crucial part of that is the first sentence.  It is true.

The second sentence is true in essence, though it possibly needs to be
made more accurate to deal with other cases.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:27                                                                         ` Daniel Colascione
@ 2016-08-30 17:42                                                                           ` Eli Zaretskii
  2016-08-30 17:46                                                                             ` Daniel Colascione
  2016-08-30 18:22                                                                             ` Stefan Monnier
  2016-08-30 18:00                                                                           ` Stefan Monnier
  1 sibling, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 17:42 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: acm, monnier, emacs-devel

> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Tue, 30 Aug 2016 10:27:45 -0700
> 
> +The region given to each of these functions is a conservative
> +approximation of the region about to changed.  After running the
> +before-change-functions, Emacs will make zero or more fine-grained
> +buffer changes and run after-change-functions for each.  Do not expect
> +before-change-functions and after-change-functions to be called in
> +balanced pairs.

The last sentence here is repeated afterwards, for no good reason.
(Also, the markup is missing, but that's just an aside.)

> -  Do @emph{not} expect the before-change hooks and the after-change
> -hooks be called in balanced pairs around each buffer change.  Also
> -don't expect the before-change hooks to be called for every chunk of
> -text Emacs is about to delete.  These hooks are provided on the
> -assumption that Lisp programs will use either before- or the
> -after-change hooks, but not both, and the boundaries of the region
> -where the changes happen might include more than just the actual
> -changed text, or even lump together several changes done piecemeal.
> +   Do @emph{not} expect the before-change hooks and the after-change
> +hooks be called in balanced pairs around each buffer change.
> +The before-change-functions region is a conservative bound on the zero
> +or more fine-grained changes to follow.  Emacs informs user code about
> +the actual changes to the buffer through calls to
> +after-change-functions; these fine-grained changes will always fall
> +inside the broad change region Emacs describes by calling
> +before-change-functions.

You removed the part about text deletion, which is not specific to
revert-buffer, so that information is now lost.  I don't want to lose
it.

Other than that, I don't see how your text is more accurate, it's just
a different wording dancing around the same issues trying to side-step
them by replacing one vague description by another.

If all you want is to remove this part:

  These hooks are provided on the assumption that Lisp programs will
  use either before- or the after-change hooks, but not both

then I don't necessarily mind, although I do believe it is true, and
the readers should be aware of that.

Thanks.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:42                                                                           ` Eli Zaretskii
@ 2016-08-30 17:46                                                                             ` Daniel Colascione
  2016-08-30 18:00                                                                               ` Eli Zaretskii
  2016-08-30 18:01                                                                               ` Alan Mackenzie
  2016-08-30 18:22                                                                             ` Stefan Monnier
  1 sibling, 2 replies; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 17:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: acm, monnier, emacs-devel

On 08/30/2016 10:42 AM, Eli Zaretskii wrote:
>> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
>> From: Daniel Colascione <dancol@dancol.org>
>> Date: Tue, 30 Aug 2016 10:27:45 -0700
>>
>> +The region given to each of these functions is a conservative
>> +approximation of the region about to changed.  After running the
>> +before-change-functions, Emacs will make zero or more fine-grained
>> +buffer changes and run after-change-functions for each.  Do not expect
>> +before-change-functions and after-change-functions to be called in
>> +balanced pairs.
>
> The last sentence here is repeated afterwards, for no good reason.
> (Also, the markup is missing, but that's just an aside.)

I figured it was a good idea to highlight this fact directly in the 
variable documentation blob. I can add a "see below" link.

>
>> -  Do @emph{not} expect the before-change hooks and the after-change
>> -hooks be called in balanced pairs around each buffer change.  Also
>> -don't expect the before-change hooks to be called for every chunk of
>> -text Emacs is about to delete.  These hooks are provided on the
>> -assumption that Lisp programs will use either before- or the
>> -after-change hooks, but not both, and the boundaries of the region
>> -where the changes happen might include more than just the actual
>> -changed text, or even lump together several changes done piecemeal.
>> +   Do @emph{not} expect the before-change hooks and the after-change
>> +hooks be called in balanced pairs around each buffer change.
>> +The before-change-functions region is a conservative bound on the zero
>> +or more fine-grained changes to follow.  Emacs informs user code about
>> +the actual changes to the buffer through calls to
>> +after-change-functions; these fine-grained changes will always fall
>> +inside the broad change region Emacs describes by calling
>> +before-change-functions.
>
> You removed the part about text deletion, which is not specific to
> revert-buffer, so that information is now lost.  I don't want to lose
> it.

The text deletion part is a real and serious bug. As Stefan points out, 
it makes it impossible to use b-c-f to invalidate caches.

>
> Other than that, I don't see how your text is more accurate, it's just
> a different wording dancing around the same issues trying to side-step
> them by replacing one vague description by another.

My proposed description highlights how the b-c-f region contains the 
a-c-f regions. I understand that you believe that the existing 
documentation communicates this fact, but I strongly disagree. The 
relationship between the b-c-f region and the a-c-f regions needs to be 
spelled out explicitly.


>
> If all you want is to remove this part:
>
>   These hooks are provided on the assumption that Lisp programs will
>   use either before- or the after-change hooks, but not both
>
> then I don't necessarily mind, although I do believe it is true, and
> the readers should be aware of that.

I strongly disagree. b-c-f is a perfectly good way to invalidate caches.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:42                                                                           ` Alan Mackenzie
@ 2016-08-30 17:53                                                                             ` Eli Zaretskii
  2016-08-30 18:16                                                                               ` Alan Mackenzie
  2016-08-30 18:14                                                                             ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 17:53 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: dancol, monnier, emacs-devel

> Date: Tue, 30 Aug 2016 17:42:24 +0000
> Cc: dancol@dancol.org, monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > Your attempt didn't describe the current implementation.  It described
> > what you thought it should be.
> 
> The text in question (intended for the Elisp manual) was:
> 
>   Normally the before-change-functions and the after-change-functions
>   hooks are called in balanced pairs around each buffer change, enabling
>   state to be determined in a before-change function and used in an
>   after-change function.  However on rare occasions,
>   before-change-functions is not called before a buffer change and
>   after-change-functions is thus called twice in succession.  Your
>   program should be ready to deal with such an occurrence.
> 
> The crucial part of that is the first sentence.  It is true.

We use "normally" in the manual to mean "always, unless changed by
customizations".  So the above use of that word is extremely confusing
and thus a bad idea.

And the part about "balanced pairs" is simply false, if "balanced" is
to be interpreted in its everyday's meaning.

> The second sentence is true in essence, though it possibly needs to be
> made more accurate to deal with other cases.

The current text is even more "true in essence", though.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 16:58                                                               ` Eli Zaretskii
@ 2016-08-30 17:57                                                                 ` Stefan Monnier
  2016-08-31 11:17                                                                   ` Phillip Lord
  2016-08-31 11:12                                                                 ` Phillip Lord
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 17:57 UTC (permalink / raw)
  To: emacs-devel

>> > You are setting the bar impossibly high by expecting that.
>> > Implementing what you want would need significant changes in how the
>> > insdel functions are implemented and used.  In particular, some
>> > complex changes will probably have to do things twice: once just to
>> > figure out which changes are needed, the other time to actually do
>> > that while calling the hooks in the way you want.  That's because in
>> > some situations we discover the required changes as we go, and have no
>> > idea in advance what we will find.
>> Actually, we do have some idea beforehand, as evidenced by the fact that
>> we call b-c-f with valid data.  It's just that after the fact we have
>> a more precise knowledge of what has actually been changed, so a-c-f can
>> give more precise bounds.
> I was under the impression that Phillip wanted the data be accurate,
> not just valid.

More precise (i.e. tighter bounds) is better, but valid is indispensable
(I used "valid" to mean that every change is covered by the bounds, even
though those bounds may be too lose.  I consider "invalid" to be a plain
bug, as in insert-file-contents, for example).

In Phillip's case he'd prefer to have suboptimal data than mispaired
data since in the mispaired case he just falls back to "redo
everything", which is equivalent to calling b/a-c-f with
point-min/point-max.  So the message you quoted just pointed out that as
long as b/a-c-f are paired (actually, you just need the guarantee that
to each b-c-f corresponds at most one a-c-f), you can manually make
those pairs "proper" (i.e. with identical bounds) inside your own a-c-f.

So I'm pretty sure he's more concerned about "proper pairing" than about
"utmost tightness of the bounds".

> Because if validity is the only requirement, we could always call the
> before-change hook with the limits of the entire buffer, and be done.
> Clearly, that would not be very useful, to say the least.

Indeed.  But in the case of subst-chars-in-region, what we pass to b-c-f
is suboptimal but better than point-min/max, so there's a useful middle
point between the difficult "tightest bound" and the degenerate "just
pass point-min/max".


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:46                                                                             ` Daniel Colascione
@ 2016-08-30 18:00                                                                               ` Eli Zaretskii
  2016-08-30 18:04                                                                                 ` Daniel Colascione
  2016-08-30 18:27                                                                                 ` Stefan Monnier
  2016-08-30 18:01                                                                               ` Alan Mackenzie
  1 sibling, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 18:00 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: acm, monnier, emacs-devel

> Cc: acm@muc.de, monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Tue, 30 Aug 2016 10:46:44 -0700
> 
> >> -  Do @emph{not} expect the before-change hooks and the after-change
> >> -hooks be called in balanced pairs around each buffer change.  Also
> >> -don't expect the before-change hooks to be called for every chunk of
> >> -text Emacs is about to delete.  These hooks are provided on the
> >> -assumption that Lisp programs will use either before- or the
> >> -after-change hooks, but not both, and the boundaries of the region
> >> -where the changes happen might include more than just the actual
> >> -changed text, or even lump together several changes done piecemeal.
> >> +   Do @emph{not} expect the before-change hooks and the after-change
> >> +hooks be called in balanced pairs around each buffer change.
> >> +The before-change-functions region is a conservative bound on the zero
> >> +or more fine-grained changes to follow.  Emacs informs user code about
> >> +the actual changes to the buffer through calls to
> >> +after-change-functions; these fine-grained changes will always fall
> >> +inside the broad change region Emacs describes by calling
> >> +before-change-functions.
> >
> > You removed the part about text deletion, which is not specific to
> > revert-buffer, so that information is now lost.  I don't want to lose
> > it.
> 
> The text deletion part is a real and serious bug. As Stefan points out, 
> it makes it impossible to use b-c-f to invalidate caches.

You misunderstand what Stefan says.  He says not calling the
before-change hook _at_all_ is a bug.  Not calling it for every chunk
of deleted text is not necessarily a bug, if there's a previous less
fine-grained call to the hook.  And that's what the text above
conveys: that note every chunk to be deleted will have its own call to
a hook.

> > Other than that, I don't see how your text is more accurate, it's just
> > a different wording dancing around the same issues trying to side-step
> > them by replacing one vague description by another.
> 
> My proposed description highlights how the b-c-f region contains the 
> a-c-f regions. I understand that you believe that the existing 
> documentation communicates this fact, but I strongly disagree. The 
> relationship between the b-c-f region and the a-c-f regions needs to be 
> spelled out explicitly.

They cannot be spelled out explicitly without going into a lot more
internal details that are inappropriate for the Lisp-level manual.

> > If all you want is to remove this part:
> >
> >   These hooks are provided on the assumption that Lisp programs will
> >   use either before- or the after-change hooks, but not both
> >
> > then I don't necessarily mind, although I do believe it is true, and
> > the readers should be aware of that.
> 
> I strongly disagree. b-c-f is a perfectly good way to invalidate caches.

So the readers need to know they cannot rely on that.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:27                                                                         ` Daniel Colascione
  2016-08-30 17:42                                                                           ` Eli Zaretskii
@ 2016-08-30 18:00                                                                           ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 18:00 UTC (permalink / raw)
  To: emacs-devel

> +The region given to each of these functions is a conservative
> +approximation of the region about to changed.  After running the
> +before-change-functions, Emacs will make zero or more fine-grained
> +buffer changes and run after-change-functions for each.  Do not expect
> +before-change-functions and after-change-functions to be called in
> +balanced pairs.

Looks OK to me.

> -  Do @emph{not} expect the before-change hooks and the after-change
> -hooks be called in balanced pairs around each buffer change.  Also
> -don't expect the before-change hooks to be called for every chunk of
> -text Emacs is about to delete.  These hooks are provided on the
> -assumption that Lisp programs will use either before- or the
> -after-change hooks, but not both, and the boundaries of the region
> -where the changes happen might include more than just the actual
> -changed text, or even lump together several changes done piecemeal.
> +   Do @emph{not} expect the before-change hooks and the after-change
> +hooks be called in balanced pairs around each buffer change.
> +The before-change-functions region is a conservative bound on the zero
> +or more fine-grained changes to follow.  Emacs informs user code about
> +the actual changes to the buffer through calls to
> +after-change-functions; these fine-grained changes will always fall
> +inside the broad change region Emacs describes by calling
> +before-change-functions.

Repeats the previous, but otherwise looks fine to me.
thanks,


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:46                                                                             ` Daniel Colascione
  2016-08-30 18:00                                                                               ` Eli Zaretskii
@ 2016-08-30 18:01                                                                               ` Alan Mackenzie
  2016-08-30 18:06                                                                                 ` Daniel Colascione
  1 sibling, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 18:01 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Eli Zaretskii, monnier, emacs-devel

Hello, Daniel.

On Tue, Aug 30, 2016 at 10:46:44AM -0700, Daniel Colascione wrote:
> On 08/30/2016 10:42 AM, Eli Zaretskii wrote:
> >> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> >> From: Daniel Colascione <dancol@dancol.org>
> >> Date: Tue, 30 Aug 2016 10:27:45 -0700

> >> +The region given to each of these functions is a conservative
> >> +approximation of the region about to changed.  After running the
> >> +before-change-functions, Emacs will make zero or more fine-grained
> >> +buffer changes and run after-change-functions for each.  Do not expect
> >> +before-change-functions and after-change-functions to be called in
> >> +balanced pairs.

> > The last sentence here is repeated afterwards, for no good reason.
> > (Also, the markup is missing, but that's just an aside.)

> I figured it was a good idea to highlight this fact directly in the 
> variable documentation blob. I can add a "see below" link.

Why are you advocating this?  It is not true.  You _can_ expect b-c-f and
a-c-f to be balanced in all but, perhaps, one occurrence per million.  It
happens so seldom that in practice, one can assume that b-c-f and a-c-f
match completely[*].  You are describing the exception as though it were the
typical case.

[*] provided the exceptions are handled somehow.

[ .... ]

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:00                                                                               ` Eli Zaretskii
@ 2016-08-30 18:04                                                                                 ` Daniel Colascione
  2016-08-30 18:46                                                                                   ` Eli Zaretskii
  2016-08-30 18:27                                                                                 ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 18:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: acm, monnier, emacs-devel

On 08/30/2016 11:00 AM, Eli Zaretskii wrote:
>> Cc: acm@muc.de, monnier@iro.umontreal.ca, emacs-devel@gnu.org
>> From: Daniel Colascione <dancol@dancol.org>
>> Date: Tue, 30 Aug 2016 10:46:44 -0700
>>
>>>> -  Do @emph{not} expect the before-change hooks and the after-change
>>>> -hooks be called in balanced pairs around each buffer change.  Also
>>>> -don't expect the before-change hooks to be called for every chunk of
>>>> -text Emacs is about to delete.  These hooks are provided on the
>>>> -assumption that Lisp programs will use either before- or the
>>>> -after-change hooks, but not both, and the boundaries of the region
>>>> -where the changes happen might include more than just the actual
>>>> -changed text, or even lump together several changes done piecemeal.
>>>> +   Do @emph{not} expect the before-change hooks and the after-change
>>>> +hooks be called in balanced pairs around each buffer change.
>>>> +The before-change-functions region is a conservative bound on the zero
>>>> +or more fine-grained changes to follow.  Emacs informs user code about
>>>> +the actual changes to the buffer through calls to
>>>> +after-change-functions; these fine-grained changes will always fall
>>>> +inside the broad change region Emacs describes by calling
>>>> +before-change-functions.
>>>
>>> You removed the part about text deletion, which is not specific to
>>> revert-buffer, so that information is now lost.  I don't want to lose
>>> it.
>>
>> The text deletion part is a real and serious bug. As Stefan points out,
>> it makes it impossible to use b-c-f to invalidate caches.
>
> You misunderstand what Stefan says.  He says not calling the
> before-change hook _at_all_ is a bug.  Not calling it for every chunk
> of deleted text is not necessarily a bug, if there's a previous less
> fine-grained call to the hook.  And that's what the text above
> conveys: that note every chunk to be deleted will have its own call to
> a hook.

So we're in agreement? True or false: b-c-f ought to be a conservative 
bound on subsequent a-c-f calls.

>
>>> Other than that, I don't see how your text is more accurate, it's just
>>> a different wording dancing around the same issues trying to side-step
>>> them by replacing one vague description by another.
>>
>> My proposed description highlights how the b-c-f region contains the
>> a-c-f regions. I understand that you believe that the existing
>> documentation communicates this fact, but I strongly disagree. The
>> relationship between the b-c-f region and the a-c-f regions needs to be
>> spelled out explicitly.
>
> They cannot be spelled out explicitly without going into a lot more
> internal details that are inappropriate for the Lisp-level manual.

Not the case at all. That's the point of saying b-c-f is a conservative 
bound. The words "conservative bound" free you from having to describe 
the precise ways the b-c-f region and the a-c-f region can differ.

>
>>> If all you want is to remove this part:
>>>
>>>   These hooks are provided on the assumption that Lisp programs will
>>>   use either before- or the after-change hooks, but not both
>>>
>>> then I don't necessarily mind, although I do believe it is true, and
>>> the readers should be aware of that.
>>
>> I strongly disagree. b-c-f is a perfectly good way to invalidate caches.
>
> So the readers need to know they cannot rely on that.

Why shouldn't they be able to rely on that? What *should* they use to 
invalidate caches? Your position is not very clear to me.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:01                                                                               ` Alan Mackenzie
@ 2016-08-30 18:06                                                                                 ` Daniel Colascione
  2016-08-30 18:17                                                                                   ` Daniel Colascione
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 18:06 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Eli Zaretskii, monnier, emacs-devel

On 08/30/2016 11:01 AM, Alan Mackenzie wrote:
> Hello, Daniel.
>
> On Tue, Aug 30, 2016 at 10:46:44AM -0700, Daniel Colascione wrote:
>> On 08/30/2016 10:42 AM, Eli Zaretskii wrote:
>>>> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
>>>> From: Daniel Colascione <dancol@dancol.org>
>>>> Date: Tue, 30 Aug 2016 10:27:45 -0700
>
>>>> +The region given to each of these functions is a conservative
>>>> +approximation of the region about to changed.  After running the
>>>> +before-change-functions, Emacs will make zero or more fine-grained
>>>> +buffer changes and run after-change-functions for each.  Do not expect
>>>> +before-change-functions and after-change-functions to be called in
>>>> +balanced pairs.
>
>>> The last sentence here is repeated afterwards, for no good reason.
>>> (Also, the markup is missing, but that's just an aside.)
>
>> I figured it was a good idea to highlight this fact directly in the
>> variable documentation blob. I can add a "see below" link.
>
> Why are you advocating this?  It is not true.  You _can_ expect b-c-f and
> a-c-f to be balanced in all but, perhaps, one occurrence per million.  It
> happens so seldom that in practice, one can assume that b-c-f and a-c-f
> match completely[*].  You are describing the exception as though it were the
> typical case.
>
> [*] provided the exceptions are handled somehow.
>
> [ .... ]
>

I'd vastly prefer the calls to be balanced. It looks like it will be 
difficult to make them that way, so describing in the manual behavior 
that preserves most of the goodness and spells out the workarounds mode 
authors need to use seems like the least awful approach.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:42                                                                           ` Alan Mackenzie
  2016-08-30 17:53                                                                             ` Eli Zaretskii
@ 2016-08-30 18:14                                                                             ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 18:14 UTC (permalink / raw)
  To: emacs-devel

>   Normally the before-change-functions and the after-change-functions
>   hooks are called in balanced pairs around each buffer change,

I could agree with that.

>   enabling state to be determined in a before-change function and used in an
>   after-change function.

But this encourages reliance on this pairing, even though experience
shows that it's better to try not to rely on it (both in the sense that
I personally believe that it results in better designs, and in the
sense that such designs will break down in the non-"normal" case).

So I'm strongly opposed to such statements.

>   However on rare occasions, before-change-functions is not called
>   before a buffer change and

That would be documenting bugs as being normal behavior.

>   after-change-functions is thus called twice in succession.  Your
>   program should be ready to deal with such an occurrence.

Two successive calls of a-c-f are indeed acceptable and code should be
ready to deal with such occurrence, but only because a previous b-c-f
call covered both changes, not because b-c-f failed to be called.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:53                                                                             ` Eli Zaretskii
@ 2016-08-30 18:16                                                                               ` Alan Mackenzie
  2016-08-30 18:51                                                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 18:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: dancol, monnier, emacs-devel

Hello, Eli.

On Tue, Aug 30, 2016 at 08:53:48PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 30 Aug 2016 17:42:24 +0000
> > Cc: dancol@dancol.org, monnier@iro.umontreal.ca, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

> > > Your attempt didn't describe the current implementation.  It described
> > > what you thought it should be.

> > The text in question (intended for the Elisp manual) was:

> >   Normally the before-change-functions and the after-change-functions
> >   hooks are called in balanced pairs around each buffer change, enabling
> >   state to be determined in a before-change function and used in an
> >   after-change function.  However on rare occasions,
> >   before-change-functions is not called before a buffer change and
> >   after-change-functions is thus called twice in succession.  Your
> >   program should be ready to deal with such an occurrence.
 
> > The crucial part of that is the first sentence.  It is true.

> We use "normally" in the manual to mean "always, unless changed by
> customizations".  So the above use of that word is extremely confusing
> and thus a bad idea.

  The before-change-functions and after-change-functions hooks are
  almost always called in balanced pairs around each buffer change,
  enabling state to be determined in a before-change-function and used
  in an after-change-function.  However, on rare occasions, ....

> And the part about "balanced pairs" is simply false, if "balanced" is
> to be interpreted in its everyday's meaning.

I don't understand what you mean.  By balanced, I essentially mean that
(i) b-c-f and a-c-f alternate,
(ii) b-c-f's beg is the same as a-c-f's beg,
(iii) b-c-f's (- end beg) is equal to a-c-f's old-len.

In that sense b/a-c-f are balanced in the overwhelming majority of
cases.


> > The second sentence is true in essence, though it possibly needs to be
> > made more accurate to deal with other cases.

> The current text is even more "true in essence", though.

No it's not.  It describes the exceptional and rare case as though it
were common.  It implies that using b/a-c-f together is not a
practicable programming technique, whereas the opposite is true.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:06                                                                                 ` Daniel Colascione
@ 2016-08-30 18:17                                                                                   ` Daniel Colascione
  2016-08-30 18:30                                                                                     ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 18:17 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Eli Zaretskii, monnier, emacs-devel

On 08/30/2016 11:06 AM, Daniel Colascione wrote:
> On 08/30/2016 11:01 AM, Alan Mackenzie wrote:
>> Hello, Daniel.
>>
>> On Tue, Aug 30, 2016 at 10:46:44AM -0700, Daniel Colascione wrote:
>>> On 08/30/2016 10:42 AM, Eli Zaretskii wrote:
>>>>> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
>>>>> From: Daniel Colascione <dancol@dancol.org>
>>>>> Date: Tue, 30 Aug 2016 10:27:45 -0700
>>
>>>>> +The region given to each of these functions is a conservative
>>>>> +approximation of the region about to changed.  After running the
>>>>> +before-change-functions, Emacs will make zero or more fine-grained
>>>>> +buffer changes and run after-change-functions for each.  Do not
>>>>> expect
>>>>> +before-change-functions and after-change-functions to be called in
>>>>> +balanced pairs.
>>
>>>> The last sentence here is repeated afterwards, for no good reason.
>>>> (Also, the markup is missing, but that's just an aside.)
>>
>>> I figured it was a good idea to highlight this fact directly in the
>>> variable documentation blob. I can add a "see below" link.
>>
>> Why are you advocating this?  It is not true.

It's not true. If it's true except for one time in a million, it's not 
true. Programs need to be written for the world we inhabit, not the one 
we want. Relying on behavior that's usually but not always the case is 
antithetical to software robustness.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:42                                                                           ` Eli Zaretskii
  2016-08-30 17:46                                                                             ` Daniel Colascione
@ 2016-08-30 18:22                                                                             ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 18:22 UTC (permalink / raw)
  To: emacs-devel

>> -  Do @emph{not} expect the before-change hooks and the after-change
>> -hooks be called in balanced pairs around each buffer change.  Also
>> -don't expect the before-change hooks to be called for every chunk of
>> -text Emacs is about to delete.  These hooks are provided on the
>> -assumption that Lisp programs will use either before- or the
>> -after-change hooks, but not both, and the boundaries of the region
>> -where the changes happen might include more than just the actual
>> -changed text, or even lump together several changes done piecemeal.
>> +   Do @emph{not} expect the before-change hooks and the after-change
>> +hooks be called in balanced pairs around each buffer change.
>> +The before-change-functions region is a conservative bound on the zero
>> +or more fine-grained changes to follow.  Emacs informs user code about
>> +the actual changes to the buffer through calls to
>> +after-change-functions; these fine-grained changes will always fall
>> +inside the broad change region Emacs describes by calling
>> +before-change-functions.

> You removed the part about text deletion, which is not specific to
> revert-buffer, so that information is now lost.  I don't want to
> lose it.

I do want to lose it, because this failure to call b-c-f is a bug, not
something part of the intended behavior.

I could live with something like "There are still some known bugs in
which b-c-f fails to be called", tho.

> Other than that, I don't see how your text is more accurate, it's just
> a different wording dancing around the same issues trying to side-step
> them by replacing one vague description by another.

They do seem mostly equivalent, so if it can satisfy one of the
complainant I'm happy to accept the change ;-)


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:00                                                                               ` Eli Zaretskii
  2016-08-30 18:04                                                                                 ` Daniel Colascione
@ 2016-08-30 18:27                                                                                 ` Stefan Monnier
  2016-09-01 13:46                                                                                   ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 18:27 UTC (permalink / raw)
  To: emacs-devel

> You misunderstand what Stefan says.  He says not calling the
> before-change hook _at_all_ is a bug.  Not calling it for every chunk
> of deleted text is not necessarily a bug, if there's a previous less
> fine-grained call to the hook.  And that's what the text above
> conveys: that note every chunk to be deleted will have its own call to
> a hook.

FWIW, when I read

    hooks be called in balanced pairs around each buffer change.  Also
    don't expect the before-change hooks to be called for every chunk of
    text Emacs is about to delete.  These hooks are provided on the

I do understand this to mean "b-c-f is just unreliable" and more
specifically it does sound to me like it refers to the known
insert-file-contents bug.  If that was not your intention, then consider
this as evidence that a rewording could be beneficial.

>> My proposed description highlights how the b-c-f region contains the 
>> a-c-f regions. I understand that you believe that the existing 
>> documentation communicates this fact, but I strongly disagree. The 
>> relationship between the b-c-f region and the a-c-f regions needs to be 
>> spelled out explicitly.
> They cannot be spelled out explicitly without going into a lot more
> internal details that are inappropriate for the Lisp-level manual.

He considers his text to spell it in enough detail.  So unless you
disagree with the text itself, I think his text is an improvement: you
both agree with the validity and level of precision of the description
in his new text, which is not the case with the current text.

>> I strongly disagree. b-c-f is a perfectly good way to invalidate caches.
> So the readers need to know they cannot rely on that.

syntax-ppss relies on it, so we had better make sure we can rely on
it ;-0


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:17                                                                                   ` Daniel Colascione
@ 2016-08-30 18:30                                                                                     ` Alan Mackenzie
  2016-08-30 18:32                                                                                       ` Daniel Colascione
  2016-08-30 18:36                                                                                       ` Stefan Monnier
  0 siblings, 2 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 18:30 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Eli Zaretskii, monnier, emacs-devel

Hello, Daniel.

On Tue, Aug 30, 2016 at 11:17:48AM -0700, Daniel Colascione wrote:
> On 08/30/2016 11:06 AM, Daniel Colascione wrote:
> > On 08/30/2016 11:01 AM, Alan Mackenzie wrote:

> >> On Tue, Aug 30, 2016 at 10:46:44AM -0700, Daniel Colascione wrote:
> >>> On 08/30/2016 10:42 AM, Eli Zaretskii wrote:
> >>>>> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> >>>>> From: Daniel Colascione <dancol@dancol.org>
> >>>>> Date: Tue, 30 Aug 2016 10:27:45 -0700

> >>>>> +The region given to each of these functions is a conservative
> >>>>> +approximation of the region about to changed.  After running the
> >>>>> +before-change-functions, Emacs will make zero or more fine-grained
> >>>>> +buffer changes and run after-change-functions for each.  Do not
> >>>>> expect
> >>>>> +before-change-functions and after-change-functions to be called in
> >>>>> +balanced pairs.

> >>>> The last sentence here is repeated afterwards, for no good reason.
> >>>> (Also, the markup is missing, but that's just an aside.)

> >>> I figured it was a good idea to highlight this fact directly in the
> >>> variable documentation blob. I can add a "see below" link.

> >> Why are you advocating this?  It is not true.

> It's not true. If it's true except for one time in a million, it's not 
> true.

That's straying off-topic into philosophy.

> Programs need to be written for the world we inhabit, not the one 
> we want. Relying on behavior that's usually but not always the case is 
> antithetical to software robustness.

Coming back to the concrete, your proposed way of expressing things
would prevent future hackers from using b-c-f and a-c-f together the way
that we do.  Is that what you want?

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:30                                                                                     ` Alan Mackenzie
@ 2016-08-30 18:32                                                                                       ` Daniel Colascione
  2016-08-30 18:47                                                                                         ` Alan Mackenzie
  2016-08-30 18:36                                                                                       ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 18:32 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Eli Zaretskii, monnier, emacs-devel



On August 30, 2016 11:30:09 AM PDT, Alan Mackenzie <acm@muc.de> wrote:
>Hello, Daniel.
>
>On Tue, Aug 30, 2016 at 11:17:48AM -0700, Daniel Colascione wrote:
>> On 08/30/2016 11:06 AM, Daniel Colascione wrote:
>> > On 08/30/2016 11:01 AM, Alan Mackenzie wrote:
>
>> >> On Tue, Aug 30, 2016 at 10:46:44AM -0700, Daniel Colascione wrote:
>> >>> On 08/30/2016 10:42 AM, Eli Zaretskii wrote:
>> >>>>> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
>> >>>>> From: Daniel Colascione <dancol@dancol.org>
>> >>>>> Date: Tue, 30 Aug 2016 10:27:45 -0700
>
>> >>>>> +The region given to each of these functions is a conservative
>> >>>>> +approximation of the region about to changed.  After running
>the
>> >>>>> +before-change-functions, Emacs will make zero or more
>fine-grained
>> >>>>> +buffer changes and run after-change-functions for each.  Do
>not
>> >>>>> expect
>> >>>>> +before-change-functions and after-change-functions to be
>called in
>> >>>>> +balanced pairs.
>
>> >>>> The last sentence here is repeated afterwards, for no good
>reason.
>> >>>> (Also, the markup is missing, but that's just an aside.)
>
>> >>> I figured it was a good idea to highlight this fact directly in
>the
>> >>> variable documentation blob. I can add a "see below" link.
>
>> >> Why are you advocating this?  It is not true.
>
>> It's not true. If it's true except for one time in a million, it's
>not 
>> true.
>
>That's straying off-topic into philosophy.

Just defining terms

>
>> Programs need to be written for the world we inhabit, not the one 
>> we want. Relying on behavior that's usually but not always the case
>is 
>> antithetical to software robustness.
>
>Coming back to the concrete, your proposed way of expressing things
>would prevent future hackers from using b-c-f and a-c-f together the
>way
>that we do.  Is that what you want?

It doesn't prevent them per second: it just forces them to be more careful. I'd prefer that these hooks work the way we both want, but if that's not the case, I'd rather not mislead developers. It's not the documentation that prevents this use, but the Emacs core




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:30                                                                                     ` Alan Mackenzie
  2016-08-30 18:32                                                                                       ` Daniel Colascione
@ 2016-08-30 18:36                                                                                       ` Stefan Monnier
  1 sibling, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 18:36 UTC (permalink / raw)
  To: emacs-devel

> Coming back to the concrete, your proposed way of expressing things
> would prevent future hackers from using b-c-f and a-c-f together the way
> that we do.  Is that what you want?

Not at all.  It just tells them what could happen in the general case,
so they can properly detect the general case and know what to do when
it happens.


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:04                                                                                 ` Daniel Colascione
@ 2016-08-30 18:46                                                                                   ` Eli Zaretskii
  2016-08-30 18:58                                                                                     ` Daniel Colascione
  2016-08-30 21:46                                                                                     ` Stefan Monnier
  0 siblings, 2 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 18:46 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: acm, monnier, emacs-devel

> Cc: acm@muc.de, monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Daniel Colascione <dancol@dancol.org>
> Date: Tue, 30 Aug 2016 11:04:07 -0700
> 
> > You misunderstand what Stefan says.  He says not calling the
> > before-change hook _at_all_ is a bug.  Not calling it for every chunk
> > of deleted text is not necessarily a bug, if there's a previous less
> > fine-grained call to the hook.  And that's what the text above
> > conveys: that note every chunk to be deleted will have its own call to
> > a hook.
> 
> So we're in agreement? True or false: b-c-f ought to be a conservative 
> bound on subsequent a-c-f calls.

Of course we are in agreement, about the essence.  Your text saus the
same as mine, except that I don't find "conservative bound" to be more
helpful than what I wrote, quite the contrary.

> >> I strongly disagree. b-c-f is a perfectly good way to invalidate caches.
> >
> > So the readers need to know they cannot rely on that.
> 
> Why shouldn't they be able to rely on that? What *should* they use to 
> invalidate caches? Your position is not very clear to me.

Stefan described the alternatives up-thread.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:32                                                                                       ` Daniel Colascione
@ 2016-08-30 18:47                                                                                         ` Alan Mackenzie
  2016-08-30 18:55                                                                                           ` Daniel Colascione
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 18:47 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: Eli Zaretskii, monnier, emacs-devel

Hello, Daniel.

On Tue, Aug 30, 2016 at 11:32:42AM -0700, Daniel Colascione wrote:


> On August 30, 2016 11:30:09 AM PDT, Alan Mackenzie <acm@muc.de> wrote:

[ .... ]

> >> Programs need to be written for the world we inhabit, not the one 
> >> we want. Relying on behavior that's usually but not always the case
> >> is antithetical to software robustness.

We build error handling into software.  Coping with non-matching b-c-f
and a-c-f calls is simply error handling.

> >Coming back to the concrete, your proposed way of expressing things
> >would prevent future hackers from using b-c-f and a-c-f together the
> >way that we do.  Is that what you want?

> It doesn't prevent them per second: it just forces them to be more careful.

Your wording would prevent such use, so clearly does it express that
b-c-f and a-c-f frequently don't match.

> I'd prefer that these hooks work the way we both want, but if that's
> not the case, I'd rather not mislead developers. It's not the
> documentation that prevents this use, but the Emacs core

CC Mode works.  The Emacs core does not prevent it working.  Nor does it
prevent your or Phillip's software from working.

You evaded the question, so I'll put it to you again: do you want to
prevent future hackers from  using b-c-f and a-c-f together the way we
do?

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:16                                                                               ` Alan Mackenzie
@ 2016-08-30 18:51                                                                                 ` Eli Zaretskii
  2016-08-30 19:00                                                                                   ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 18:51 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: dancol, monnier, emacs-devel

> Date: Tue, 30 Aug 2016 18:16:38 +0000
> Cc: dancol@dancol.org, monnier@iro.umontreal.ca, emacs-devel@gnu.org
> From: Alan Mackenzie <acm@muc.de>
> 
> > And the part about "balanced pairs" is simply false, if "balanced" is
> > to be interpreted in its everyday's meaning.
> 
> I don't understand what you mean.  By balanced, I essentially mean that
> (i) b-c-f and a-c-f alternate,
> (ii) b-c-f's beg is the same as a-c-f's beg,
> (iii) b-c-f's (- end beg) is equal to a-c-f's old-len.

That's just it: the above happens only in "simple" changes, like a
simple deletion or insertion.  Any more complex changes don't do it
"balanced" according to your definition.

Look, do we have to reiterate this endless discussion that leads
nowhere?  I wasted all my free time today reading and replying to
messages about this, something that I thought was closed long ago.
Important patches that were ready to be applied and pushed are still
waiting because I didn't have time for them.

I suggest that we leave it alone -- again.

Thanks.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:47                                                                                         ` Alan Mackenzie
@ 2016-08-30 18:55                                                                                           ` Daniel Colascione
  2016-08-30 19:14                                                                                             ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 18:55 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Eli Zaretskii, monnier, emacs-devel



On August 30, 2016 11:47:49 AM PDT, Alan Mackenzie <acm@muc.de> wrote:
>Hello, Daniel.
>
>On Tue, Aug 30, 2016 at 11:32:42AM -0700, Daniel Colascione wrote:
>
>
>> On August 30, 2016 11:30:09 AM PDT, Alan Mackenzie <acm@muc.de>
>wrote:
>
>[ .... ]
>
>> >> Programs need to be written for the world we inhabit, not the one 
>> >> we want. Relying on behavior that's usually but not always the
>case
>> >> is antithetical to software robustness.
>
>We build error handling into software.  Coping with non-matching b-c-f
>and a-c-f calls is simply error handling.
>
>> >Coming back to the concrete, your proposed way of expressing things
>> >would prevent future hackers from using b-c-f and a-c-f together the
>> >way that we do.  Is that what you want?
>
>> It doesn't prevent them per second: it just forces them to be more
>careful.
>
>Your wording would prevent such use, so clearly does it express that
>b-c-f and a-c-f frequently don't match.
>
>> I'd prefer that these hooks work the way we both want, but if that's
>> not the case, I'd rather not mislead developers. It's not the
>> documentation that prevents this use, but the Emacs core
>
>CC Mode works.  The Emacs core does not prevent it working.  Nor does
>it
>prevent your or Phillip's software from working.
>
>You evaded the question, so I'll put it to you again: do you want to
>prevent future hackers from  using b-c-f and a-c-f together the way we
>do?

Yes, because the approach we use today is broken and there's little hope in fixing it. The language in the documentation doesn't change what Emacs does. I don't understand what's so hard to see. You want to lead developers into writing code against an Emacs that doesn't exist



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:46                                                                                   ` Eli Zaretskii
@ 2016-08-30 18:58                                                                                     ` Daniel Colascione
  2016-08-30 19:17                                                                                       ` Eli Zaretskii
  2016-08-30 21:46                                                                                     ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Daniel Colascione @ 2016-08-30 18:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: acm, monnier, emacs-devel



On August 30, 2016 11:46:24 AM PDT, Eli Zaretskii <eliz@gnu.org> wrote:
>> Cc: acm@muc.de, monnier@iro.umontreal.ca, emacs-devel@gnu.org
>> From: Daniel Colascione <dancol@dancol.org>
>> Date: Tue, 30 Aug 2016 11:04:07 -0700
>> 
>> > You misunderstand what Stefan says.  He says not calling the
>> > before-change hook _at_all_ is a bug.  Not calling it for every
>chunk
>> > of deleted text is not necessarily a bug, if there's a previous
>less
>> > fine-grained call to the hook.  And that's what the text above
>> > conveys: that note every chunk to be deleted will have its own call
>to
>> > a hook.
>> 
>> So we're in agreement? True or false: b-c-f ought to be a
>conservative 
>> bound on subsequent a-c-f calls.
>
>Of course we are in agreement, about the essence.  Your text saus the
>same as mine, except that I don't find "conservative bound" to be more
>helpful than what I wrote, quite the contrary.

Your text is silent on the relationship between the regions given to b-c-f and the ones given to b-c-f. I don't understand what's so hard to see. My proposed change tightens the contract between the Emacs core and developers and does it in a way that doesn't impose additional requirements on the current implementation.


>
>> >> I strongly disagree. b-c-f is a perfectly good way to invalidate
>caches.
>> >
>> > So the readers need to know they cannot rely on that.
>> 
>> Why shouldn't they be able to rely on that? What *should* they use to
>
>> invalidate caches? Your position is not very clear to me.
>
>Stefan described the alternatives up-thread.


Those alternatives are all incredibly awkward



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:51                                                                                 ` Eli Zaretskii
@ 2016-08-30 19:00                                                                                   ` Alan Mackenzie
  0 siblings, 0 replies; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 19:00 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: dancol, monnier, emacs-devel

Hello, Eli.

On Tue, Aug 30, 2016 at 09:51:20PM +0300, Eli Zaretskii wrote:
> > Date: Tue, 30 Aug 2016 18:16:38 +0000
> > Cc: dancol@dancol.org, monnier@iro.umontreal.ca, emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>

[ .... ]

> Look, do we have to reiterate this endless discussion that leads
> nowhere?  I wasted all my free time today reading and replying to
> messages about this, something that I thought was closed long ago.
> Important patches that were ready to be applied and pushed are still
> waiting because I didn't have time for them.

> I suggest that we leave it alone -- again.

I think these matters are important.  Very important.  Critically
important even, because they set an upper bound on Emacs's future
capabilities.

But I think we've both said everything that's to be said, so OK, let's
leave it alone.

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:55                                                                                           ` Daniel Colascione
@ 2016-08-30 19:14                                                                                             ` Alan Mackenzie
  2016-08-30 20:34                                                                                               ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 19:14 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: monnier, emacs-devel

Hello, Daniel.

On Tue, Aug 30, 2016 at 11:55:41AM -0700, Daniel Colascione wrote:


> On August 30, 2016 11:47:49 AM PDT, Alan Mackenzie <acm@muc.de> wrote:

> >Do you want to prevent future hackers from  using b-c-f and a-c-f
> >together the way we do?

> Yes, because the approach we use today is broken and there's little
> hope in fixing it.

There is software that cannot be written in any reasonable fashion
without the technique under discussion.  I suspect, even if I don't know
for sure, that CC Mode comes into that category.  Any lisp program which
requires full details of a change cannot be reasonably written without the
technique.

Documenting, falsely, that it doesn't work restricts the set of what can
be written for Emacs.

> The language in the documentation doesn't change what Emacs does. I
> don't understand what's so hard to see. You want to lead developers
> into writing code against an Emacs that doesn't exist.

No, I quite clearly and accurately described the Emacs that does exist:
The technique works almost always, but you have to detect and handle
exceptions carefully, something that can be easily done.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:58                                                                                     ` Daniel Colascione
@ 2016-08-30 19:17                                                                                       ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-30 19:17 UTC (permalink / raw)
  To: Daniel Colascione; +Cc: acm, monnier, emacs-devel

> From: Daniel Colascione <dancol@dancol.org>
> Date: Tue, 30 Aug 2016 11:58:04 -0700
> CC: acm@muc.de,monnier@iro.umontreal.ca,emacs-devel@gnu.org
> 
> Your text is silent on the relationship between the regions given to b-c-f and the ones given to b-c-f.

It's not silent.  It tells the reader specifically what assumptions
are invalid.  I think that is much more useful in practice than
talking about conservative bounds, something that is more abstract and
therefore more easily misinterpreted/misunderstood.

> My proposed change tightens the contract between the Emacs core and developers and does it in a way that doesn't impose additional requirements on the current implementation.

With the current imperfect implementation, I don't see how that is an
advantage in practice.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 19:14                                                                                             ` Alan Mackenzie
@ 2016-08-30 20:34                                                                                               ` Stefan Monnier
  2016-08-30 20:53                                                                                                 ` Alan Mackenzie
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 20:34 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Daniel Colascione, emacs-devel

> There is software that cannot be written in any reasonable fashion
> without the technique under discussion.  I suspect, even if I don't know
> for sure, that CC Mode comes into that category.

It's trivial to demonstrate that it doesn't:
- consider any change between START and END to the buffer.
- you can always decompose it into:
  (a) delete everything from START to point-max.
  (b) insert at START (now point-max) the rest of the text.
- clearly the above deletions and insertions *could* happen, so CC-mode
  has to handle them and since all changes could be decomposed this way,
  CC-mode does not *need* to handle any other case.
- to handle (a) you don't need to know anything from b-c-f.
- to handle (b) you don't need to know anything from b-c-f.

CQFD

> No, I quite clearly and accurately described the Emacs that does exist:
> The technique works almost always, but you have to detect and handle
> exceptions carefully, something that can be easily done.

Daniel's description gives you the added info necessary to know how to
detect that situation and what you might want to do about it.

FWIW, I like Daniel's wording.  It is about as precise as we can make it
without imposing undue burden (IOW I think Emacs's implementation can
reasonably (and should) obey that description) and I think it gives the
right intuition.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 20:34                                                                                               ` Stefan Monnier
@ 2016-08-30 20:53                                                                                                 ` Alan Mackenzie
  2016-08-30 21:37                                                                                                   ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Alan Mackenzie @ 2016-08-30 20:53 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Daniel Colascione, emacs-devel

Hello, Stefan.

On Tue, Aug 30, 2016 at 04:34:46PM -0400, Stefan Monnier wrote:
> > There is software that cannot be written in any reasonable fashion
> > without the technique under discussion.  I suspect, even if I don't know
> > for sure, that CC Mode comes into that category.

> It's trivial to demonstrate that it doesn't:
> - consider any change between START and END to the buffer.
> - you can always decompose it into:
>   (a) delete everything from START to point-max.
>   (b) insert at START (now point-max) the rest of the text.
> - clearly the above deletions and insertions *could* happen, so CC-mode
>   has to handle them and since all changes could be decomposed this way,
>   CC-mode does not *need* to handle any other case.
> - to handle (a) you don't need to know anything from b-c-f.
> - to handle (b) you don't need to know anything from b-c-f.

That's garbage.  Pure garbage.  I said above in any _REASONABLE_
fashion, specifically excluding, in the bit you snipped, scanning from
BOB on every single change.

Even you would start complaining if CC Mode slowed to the slowness it
would have on implementing anything like you're suggesting.

> CQFD

????

> > No, I quite clearly and accurately described the Emacs that does exist:
> > The technique works almost always, but you have to detect and handle
> > exceptions carefully, something that can be easily done.

> Daniel's description gives you the added info necessary to know how to
> detect that situation and what you might want to do about it.

No, Daniel's description, also Eli's description, by any reasonable
reading, completely exclude the use of the technique, using words
like "expect", but using it to mean something different from its
everyday meaning.  I expect b-c-f and a-c-f to match in the same way I
expect to cross the road without being knocked down by a lorry.  It's
the normal event, though not 100% guaranteed.

Nowhere do Daniel or Eli document the reality, that b-c-f and a-c-f
match very close to 100% of the time.  The elisp manual places an upper
limit on what hackers can do with Emacs.  That limit is now lower than
it was before 25.1.  I find that a very sad state of affairs.

> FWIW, I like Daniel's wording.  It is about as precise as we can make it
> without imposing undue burden (IOW I think Emacs's implementation can
> reasonably (and should) obey that description) and I think it gives the
> right intuition.

I disagree with you totally.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 20:53                                                                                                 ` Alan Mackenzie
@ 2016-08-30 21:37                                                                                                   ` Stefan Monnier
  0 siblings, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 21:37 UTC (permalink / raw)
  To: emacs-devel

>> It's trivial to demonstrate that it doesn't:
>> - consider any change between START and END to the buffer.
>> - you can always decompose it into:
>> (a) delete everything from START to point-max.
>> (b) insert at START (now point-max) the rest of the text.
>> - clearly the above deletions and insertions *could* happen, so CC-mode
>> has to handle them and since all changes could be decomposed this way,
>> CC-mode does not *need* to handle any other case.
>> - to handle (a) you don't need to know anything from b-c-f.
>> - to handle (b) you don't need to know anything from b-c-f.

> That's garbage.  Pure garbage.  I said above in any _REASONABLE_
> fashion, specifically excluding, in the bit you snipped, scanning from
> BOB on every single change.

[ You said "written in any reasonable fashion", so I took it you
  referred to the complexity of the code-writing part, not the runtime
  complexity of the algorithm.  As a matter of fact the above
  suggestion makes the code's writing *more* reasonable since you have
  to handle fewer distinct cases.  ]

Nothing in the above requires scanning from BOB.
And it's reasonable enough (in terms of performance) for all other known
major modes, BTW.

> Even you would start complaining if CC Mode slowed to the slowness it
> would have on implementing anything like you're suggesting.

As a matter fact, my local CC-mode works just the way I describe above
(via syntax-propertize), and I haven't noticed any slowness so far.

>> Daniel's description gives you the added info necessary to know how to
>> detect that situation and what you might want to do about it.
> No, Daniel's description, also Eli's description, by any reasonable
> reading, completely exclude the use of the technique,

Daniel's wording (and Eli as well, tho maybe slightly less crisply) say
precisely what might come up and does not exclude the technique you use.

You could argue that it lacks an argument of what is *frequent*, which
might influence the design choice, but it in no way restrict the
*possible* designs.

> Nowhere do Daniel or Eli document the reality, that b-c-f and a-c-f
> match very close to 100% of the time.

I think it's OK.  As you and Daniel have argued, it's "natural" for the
reader to presume that b-c-f and a-c-f will always come in perfect pairs
(and that's also what they will quickly find out when testing or
debugging their code), so there's no need to reinforce this natural
assumption.  Instead what the doc needs to focus on is the fact that
this presumption is not always valid and clarify *how* it's invalid.

> The elisp manual places an upper limit on what hackers can do with
> Emacs.  That limit is now lower than it was before 25.1.  I find that
> a very sad state of affairs.

Your CC-mode design is actually correct w.r.t Daniel's wording.
Its good performance is not guaranteed by this wording since it handles
the non-paired case suboptimally but we rarely (if ever) document
performance-related specification anyway, so most code's performance
design is based on experiments rather than on reading the doc.

> I disagree with you totally.

Wonderful!  On the upside, you might like to take a look at the closely
related bug#24340 where you might actually agree with me for once ;-)


        Stefan




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:46                                                                                   ` Eli Zaretskii
  2016-08-30 18:58                                                                                     ` Daniel Colascione
@ 2016-08-30 21:46                                                                                     ` Stefan Monnier
  2016-08-31  2:38                                                                                       ` Eli Zaretskii
  1 sibling, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-30 21:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: acm, Daniel Colascione, emacs-devel

> Of course we are in agreement, about the essence.  Your text saus the
> same as mine, except that I don't find "conservative bound" to be more
> helpful than what I wrote, quite the contrary.

Let's take a step back:

We have 4 people in this thread who have trouble agreeing about a tiny
spot of the doc but really want to see some closure.  Current doc's
score:

   Alan: -1
   Daniel: -1
   Eli: +1
   Stef: 0

Where 0 means I can live with it.  Daniel's doc's score:

   Alan: -1
   Daniel: +1
   Stef: +1
   Eli: 0

[ I based the last "0" on the above paragraph where you seem to say that
  you prefer your text, but not super strongly, IOW you can live with it.  ]

For these reason, I think we should go with Daniel's wording, which only
irks Alan and hence rubs fewer people the wrong way.  Another advantage
is that this should close this thread (I think we all know at this point
that Alan won't ever agree with what you and I would agree to, which is
why the discussion had died before Daniel came along).

Please?


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 21:46                                                                                     ` Stefan Monnier
@ 2016-08-31  2:38                                                                                       ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-31  2:38 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: acm, dancol, emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: Daniel Colascione <dancol@dancol.org>,  acm@muc.de,  emacs-devel@gnu.org
> Date: Tue, 30 Aug 2016 17:46:49 -0400
> 
> For these reason, I think we should go with Daniel's wording, which only
> irks Alan and hence rubs fewer people the wrong way.  Another advantage
> is that this should close this thread (I think we all know at this point
> that Alan won't ever agree with what you and I would agree to, which is
> why the discussion had died before Daniel came along).
> 
> Please?

No, sorry.  My opinion on this weighs more.

And please let's leave this alone, for as long as the code is as it
is.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-30 15:11         ` Stefan Monnier
@ 2016-08-31 11:00           ` Phillip Lord
  2016-08-31 12:24             ` Stefan Monnier
  2016-09-01  6:40           ` Phillip Lord
  1 sibling, 1 reply; 189+ messages in thread
From: Phillip Lord @ 2016-08-31 11:00 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>> But it can admittedly be cumbersome since the old-text is now in a string
>>> rather than being inside the buffer.
>> Because, I am not using the before and after positions just to recognise
>> the string that has changed.
>
> I was not suggesting to use those position to recognize the string:
> I was suggesting to use the suggested code to get the old-string so that
> you can then do what you need on the "before change" state.
>
>> I am have to calculate the equivalent positions in the other "lentic"
>> buffer; and this can only be done before the change, since the two
>> buffers are them in a consistent state.

Oh dear, my English seems to be terrible in this paragraph.

>
> The idea is that my suggested code gives you the needed info.
> More specifically, the other buffer is (well, should be) in a state
> consistent with "the current buffer where start..end is replaced (back)
> with `old-text'".

I think it does not, I am afraid, because the "end" position of b-c-f is
not reliably correct.

Consider this buffer:

One
Two

which is converted into this buffer

;; One
;; Two

To calulate that the "T" are cognate locations, I count the number of
lines, and then count backward from the end of the line. This works, so
long as the buffers are also cognate.

Now, say we have a deletion in buffer one starting at pos 3 ("e") to
pos 5 ("T"). Pos 3 is fine -- it's equivalent to pos 6 in the commented
buffer. But pos 5 is difficult. I have to calculate it's cognate
position before the deletion, since the number of lines change.

Which is what I do. All of this breaks if the end location on b-c-f is
wrong wrt to a-c-f. Counting the number of lines does not work on a-c-f
because the uncommented buffer has already changed.


> So that should give you the info needed to update things without doing
> a "complete flush".  As mentioned, it may be inconvenient to use it
> (depending on details of how the rest of the code is implemented) since
> the old-text is now in a string rather than being right there in
> the buffer.
>
>>> Note that in the subst-char-in-region you could "make it pairup"
>>> yourself by hand: if you have (< (+ start length) (cdr lentic--b-c-pos)),
>>> then you can just
>>> 
>>>     (let ((diff (- (cdr lentic--b-c-pos) (+ start length))))
>>>     (cl-incf length diff)
>>>     (cl-incf end diff))
>>> 
>>> such that (eq (+ start length) (cdr lentic--b-c-pos)).
>> So, this works because subst-char-in-region is guaranteed not to change
>> the size of the region right?
>
> No.  It works because a-c-f's arguments say "nothing was changed before
> START and after END", so it's always safe (conservative) to move START
> towards BOB or move END towards EOB (of course, when updating END you
> also need to update LENGTH correspondingly).


Ah, yes. But, unfortunately, I cannot calculate the location of the END
position in the cognate buffer. If subst-char-in-region did just what
you are suggesting I do (i.e. signally the maximal extent on a-c-f, as
it does on b-c-f), then there would be no problem.

I would love to change subst-char-in-region to achieve this. Making
a-c-f signal the maximal extent is the trivial change; the alternative
of having b-c-f know the real extent of the change is harder, but also
could be done.

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 13:39                                                           ` Stefan Monnier
@ 2016-08-31 11:04                                                             ` Phillip Lord
  0 siblings, 0 replies; 189+ messages in thread
From: Phillip Lord @ 2016-08-31 11:04 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> I think to really avoid the complexity for mode authors, b-c-f and a-c-f
>> need to not only balance, but also to be consistent. At the moment, they
>> are not that either -- they can signal different locations for a given
>> change.
>
> I think "balanced + a guarantee that a-c-f covers a subset of b-c-f" is
> sufficient, since you can then trivially extend a-c-f's subset to the
> corresponding "identical" locations if you need it.
>
> AFAIK we do have the "a-c-f covers a subset of b-c-f" property,
> right now (modulo bugs, of course).

To my mind, it's not enough. Even if a-c-f could signal the minimal
change AND the positions reported by b-c-f that would work for me.

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 16:58                                                               ` Eli Zaretskii
  2016-08-30 17:57                                                                 ` Stefan Monnier
@ 2016-08-31 11:12                                                                 ` Phillip Lord
  1 sibling, 0 replies; 189+ messages in thread
From: Phillip Lord @ 2016-08-31 11:12 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Stefan Monnier, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:
>> Actually, we do have some idea beforehand, as evidenced by the fact that
>> we call b-c-f with valid data.  It's just that after the fact we have
>> a more precise knowledge of what has actually been changed, so a-c-f can
>> give more precise bounds.
>
> I was under the impression that Phillip wanted the data be accurate,
> not just valid.  Because if validity is the only requirement, we could
> always call the before-change hook with the limits of the entire
> buffer, and be done.  Clearly, that would not be very useful, to say
> the least.

I want it to be as accurate as possible given the constraint of
validity. If it is invalid this breaks my use case (except that I detect
this and have an unoptimized fall back plan). If it is inaccurate (in
the sense of wider than necessary), this makes my code potentially less
efficient.

>> We could also change the C code to perform this "extension" of the
>> region passed to a-c-f so that the b-c-f region and the a-c-f region
>> match, but that would make the region passed to a-c-f less precise, so
>> those users of a-c-f which don't care about the pairing (the majority of
>> the users) would be penalized (tho they'd still work correctly: just
>> suboptimally) since there's no way for them to recover the
>> tighter region.
>
> Right.

The sad thing is that, certainly for subst-char-in-region, both of these
pieces of information are available to the code that calls a-c-f. But I
can see no clean way of signalling this information: adding the data to
a-c-f would change it's interface, and storing it in global state is
just ugly.


Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 17:57                                                                 ` Stefan Monnier
@ 2016-08-31 11:17                                                                   ` Phillip Lord
  0 siblings, 0 replies; 189+ messages in thread
From: Phillip Lord @ 2016-08-31 11:17 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> I was under the impression that Phillip wanted the data be accurate,
>> not just valid.
>
> More precise (i.e. tighter bounds) is better, but valid is indispensable
> (I used "valid" to mean that every change is covered by the bounds, even
> though those bounds may be too lose.  I consider "invalid" to be a plain
> bug, as in insert-file-contents, for example).
>
> So I'm pretty sure he's more concerned about "proper pairing" than about
> "utmost tightness of the bounds".

This is exactly correct. I think in my last email I was using "valid" to
mean consistent between b-c-f and a-c-f; sorry for confused terminology.

>
>> Because if validity is the only requirement, we could always call the
>> before-change hook with the limits of the entire buffer, and be done.
>> Clearly, that would not be very useful, to say the least.
>
> Indeed.  But in the case of subst-chars-in-region, what we pass to b-c-f
> is suboptimal but better than point-min/max, so there's a useful middle
> point between the difficult "tightest bound" and the degenerate "just
> pass point-min/max".

I think you mean "painful middle point" rather than "useful"!

Well, it's been on my list of things to do for a while. I will have
another look at subst-char-in-region, to see if I can work out whether
having b-c-f accurately signal the start is possible.

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 16:06                                                                         ` Eli Zaretskii
@ 2016-08-31 11:20                                                                           ` Phillip Lord
  2016-08-31 14:57                                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 189+ messages in thread
From: Phillip Lord @ 2016-08-31 11:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: dancol, monnier, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:
>> Can I deliberately misinterpret this as saying that you think that the
>> changes would be fine so long as we add lots of tests at the same time?
>
> Not "at the same time", but "as a prerequisite" for any serious
> consideration of such changes.  IOW, I want to see the tests first,
> decide whether I like their degree of coverage, and only then I will
> be prepared to _talk_ about any changes in this area.  And the first
> step in that talk will have to be someone presenting a rather complete
> design of the changes, including an analysis of the current callers
> and how each one (or each class) of them will work under the new
> design.


Actually, for me, any individual change that removes inconsistency
between the b-c-f and a-c-f locations is a positive thing. I already
have a fall back plan, but the fewer times this is called, the more
efficient my code gets.

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-31 11:00           ` Phillip Lord
@ 2016-08-31 12:24             ` Stefan Monnier
  2016-09-01  6:49               ` Phillip Lord
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-08-31 12:24 UTC (permalink / raw)
  To: Phillip Lord; +Cc: emacs-devel

>> The idea is that my suggested code gives you the needed info.
>> More specifically, the other buffer is (well, should be) in a state
>> consistent with "the current buffer where start..end is replaced (back)
>> with `old-text'".
> I think it does not, I am afraid, because the "end" position of b-c-f is
> not reliably correct.

The `end' position of b-c-f is correct (barring bugs), but is indeed
different from the `end' position of a-c-f (the difference is provided
by `length').

All I'm saying is that with the code I provided you could do (in a-c-f)
what Alan considered doing:

    (goto-char start)
    (let ((new-text (delete-and-extract-region start end)))
      (insert old-text)
      (let ((old-end (+ start (length old-text))))
        (run-my-b-c-f-code start old-end)
        (goto-char start)
        (delete-region start old-end)
        (insert new-text)))

Doing it this way would be really annoying, so it's better if your code
is able to work directly with `old-text' without having to insert it
into the buffer, but at least all the needed info is available.

> Ah, yes. But, unfortunately, I cannot calculate the location of the END
> position in the cognate buffer. If subst-char-in-region did just what
> you are suggesting I do (i.e. signally the maximal extent on a-c-f, as
> it does on b-c-f), then there would be no problem.

The code I provided does just that (except it does it inside a-c-f but
the result is *exactly* the same as if subst-char-in-region were to do it
for you).


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-31 11:20                                                                           ` Phillip Lord
@ 2016-08-31 14:57                                                                             ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-08-31 14:57 UTC (permalink / raw)
  To: Phillip Lord; +Cc: dancol, monnier, emacs-devel

> From: phillip.lord@russet.org.uk (Phillip Lord)
> Cc: dancol@dancol.org,  monnier@iro.umontreal.ca,  emacs-devel@gnu.org
> Date: Wed, 31 Aug 2016 12:20:21 +0100
> 
> Actually, for me, any individual change that removes inconsistency
> between the b-c-f and a-c-f locations is a positive thing. I already
> have a fall back plan, but the fewer times this is called, the more
> efficient my code gets.

Having read through the code for quite some time, I simply don't
believe this is possible.  You could fix one marginal use case (they
all are marginal), but by doing that break another.  There are too
many layers of patchwork.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-30 15:11         ` Stefan Monnier
  2016-08-31 11:00           ` Phillip Lord
@ 2016-09-01  6:40           ` Phillip Lord
  2016-09-01 13:33             ` Stefan Monnier
  1 sibling, 1 reply; 189+ messages in thread
From: Phillip Lord @ 2016-09-01  6:40 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>> Note that in the subst-char-in-region you could "make it pairup"
>>> yourself by hand: if you have (< (+ start length) (cdr lentic--b-c-pos)),
>>> then you can just
>>> 
>>>     (let ((diff (- (cdr lentic--b-c-pos) (+ start length))))
>>>     (cl-incf length diff)
>>>     (cl-incf end diff))
>>> 
>>> such that (eq (+ start length) (cdr lentic--b-c-pos)).
>> So, this works because subst-char-in-region is guaranteed not to change
>> the size of the region right?
>
> No.  It works because a-c-f's arguments say "nothing was changed before
> START and after END", so it's always safe (conservative) to move START
> towards BOB or move END towards EOB (of course, when updating END you
> also need to update LENGTH correspondingly).

Okay, yes, I understand now, and yes, this should be conservative, in
the sense that it works for all changes, I guess. We are making the
assumption here that "start" is always consistent between b-c-f and
a-c-f, and that this is never maximal in one case and minimal in the
other?

Phil




^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-08-31 12:24             ` Stefan Monnier
@ 2016-09-01  6:49               ` Phillip Lord
  2016-09-01 13:36                 ` Stefan Monnier
  0 siblings, 1 reply; 189+ messages in thread
From: Phillip Lord @ 2016-09-01  6:49 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>> The idea is that my suggested code gives you the needed info.
>>> More specifically, the other buffer is (well, should be) in a state
>>> consistent with "the current buffer where start..end is replaced (back)
>>> with `old-text'".
>> I think it does not, I am afraid, because the "end" position of b-c-f is
>> not reliably correct.
>
> The `end' position of b-c-f is correct (barring bugs), but is indeed
> different from the `end' position of a-c-f (the difference is provided
> by `length').
>
> All I'm saying is that with the code I provided you could do (in a-c-f)
> what Alan considered doing:
>
>     (goto-char start)
>     (let ((new-text (delete-and-extract-region start end)))
>       (insert old-text)
>       (let ((old-end (+ start (length old-text))))
>         (run-my-b-c-f-code start old-end)
>         (goto-char start)
>         (delete-region start old-end)
>         (insert new-text)))
>
> Doing it this way would be really annoying, so it's better if your code
> is able to work directly with `old-text' without having to insert it
> into the buffer, but at least all the needed info is available.
>
>> Ah, yes. But, unfortunately, I cannot calculate the location of the END
>> position in the cognate buffer. If subst-char-in-region did just what
>> you are suggesting I do (i.e. signally the maximal extent on a-c-f, as
>> it does on b-c-f), then there would be no problem.
>
> The code I provided does just that (except it does it inside a-c-f but
> the result is *exactly* the same as if subst-char-in-region were to do it
> for you).


So, on a-c-f revert the change, do what we are currently doing on b-c-f,
then reapply the change and run what we are currently running on a-c-f.

Yes, that does seem a possibility albeit a fairly hideous one. It's
really not something I'd want to be doing after every command.

I'll test out expanding the region with the code you suggested earlier.

  (let ((diff (- (cdr lentic--b-c-pos) (+ start length))))
     (cl-incf length diff)
     (cl-incf end diff))

and see if this works.

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-09-01  6:40           ` Phillip Lord
@ 2016-09-01 13:33             ` Stefan Monnier
  2016-09-02 11:34               ` Phillip Lord
  0 siblings, 1 reply; 189+ messages in thread
From: Stefan Monnier @ 2016-09-01 13:33 UTC (permalink / raw)
  To: Phillip Lord; +Cc: emacs-devel

> Okay, yes, I understand now, and yes, this should be conservative, in
> the sense that it works for all changes, I guess. We are making the
> assumption here that "start" is always consistent between b-c-f and
> a-c-f,

No, we don't make such an assumption either.  The assumption we make is
that the region passed to a-c-f is within the region passed to b-c-f
(i.e. is tighter).


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-09-01  6:49               ` Phillip Lord
@ 2016-09-01 13:36                 ` Stefan Monnier
  0 siblings, 0 replies; 189+ messages in thread
From: Stefan Monnier @ 2016-09-01 13:36 UTC (permalink / raw)
  To: Phillip Lord; +Cc: emacs-devel

> So, on a-c-f revert the change, do what we are currently doing on b-c-f,
> then reapply the change and run what we are currently running on a-c-f.

Yup.

> Yes, that does seem a possibility albeit a fairly hideous one.
> It's really not something I'd want to be doing after every command.

Yes, hideous sounds about right.  OTOH if your code can work straight
from the old-text string without too much gymnastics, it's not that bad.

> I'll test out expanding the region with the code you suggested earlier.

Yes, that's probably a much better option.


        Stefan



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-30 18:27                                                                                 ` Stefan Monnier
@ 2016-09-01 13:46                                                                                   ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-09-01 13:46 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Tue, 30 Aug 2016 14:27:29 -0400
> 
> > You misunderstand what Stefan says.  He says not calling the
> > before-change hook _at_all_ is a bug.  Not calling it for every chunk
> > of deleted text is not necessarily a bug, if there's a previous less
> > fine-grained call to the hook.  And that's what the text above
> > conveys: that note every chunk to be deleted will have its own call to
> > a hook.
> 
> FWIW, when I read
> 
>     hooks be called in balanced pairs around each buffer change.  Also
>     don't expect the before-change hooks to be called for every chunk of
>     text Emacs is about to delete.  These hooks are provided on the
> 
> I do understand this to mean "b-c-f is just unreliable" and more
> specifically it does sound to me like it refers to the known
> insert-file-contents bug.  If that was not your intention, then consider
> this as evidence that a rewording could be beneficial.

I was not referring to this text, I was referring to our discussion.

> He considers his text to spell it in enough detail.  So unless you
> disagree with the text itself, I think his text is an improvement: you
> both agree with the validity and level of precision of the description
> in his new text, which is not the case with the current text.

I don't think it's an improvement.  It replaces specific practical
advice with abstract principle whose relation to practice might not be
clear to some.

Really, Stefan, after all these years, I'd expect you to trust me a
bit more on documentation issues.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-08-29 14:50                                                                     ` Eli Zaretskii
                                                                                         ` (2 preceding siblings ...)
  2016-08-30 17:12                                                                       ` Alan Mackenzie
@ 2016-09-01 21:25                                                                       ` Davis Herring
  2016-09-02  7:26                                                                         ` Eli Zaretskii
  3 siblings, 1 reply; 189+ messages in thread
From: Davis Herring @ 2016-09-01 21:25 UTC (permalink / raw)
  To: Eli Zaretskii, Daniel Colascione, monnier; +Cc: emacs-devel

> This is a naïve interpretation of what a "change" means and entails.
> In reality, some changes are done with a single call to an insdel
> function, while others need multiple calls that delete and insert text
> piecemeal.  Thus the need to call the hooks before and after each
> insdel call only sometimes.

Indeed, no one knows what we mean by "change".  To make progress, we 
must introduce a formal definition for it, in particular in conjunction 
with the word "before" -- preferably a definition that the current 
implementation satisfies but that allows useful reasoning.

As has been said, some of the proposed documentation that disclaims 
"pairing" produces a definition that is satisfied but is uselessly vague 
-- allowing the implementation to simply call b-c-f once with 
(point-min) and (point-max) when the buffer is created, and never again. 
  (Changes beyond the initial (point-max) are simply insertions into 
that interval!)

However, we intuitively know that b-c-f is supposed to be called 
"immediately before" a change; what does that mean?  Certainly it is not 
a statement about the real passage of time or function calls.  It has to 
be based on an ordering of relevant events -- b-c-f calls, a-c-f calls, 
and the changes themselves.  The "properly paired" ideal defines 
"immediately before" as "with no change intervening" (and similarly for 
a-c-f), disallowing the implementation from reporting what Dan calls 
"fine-grained" changes only via a-c-f.

We can offer a weaker (but still useful) formal guarantee that the 
current implementation does satisfy phrased instead in terms of 
_absence_ of change: a call to a-c-f "publishes" an interval of text 
where changes have been completed and which shall not be altered until 
after a subsequent b-c-f call that "unlocks" it.  (These intervals act 
like rear-advancing overlays: a zero-length interval must be unlocked to 
allow an insertion, and an a-c-f call that covers an unlocked interval 
entirely destroys it without any zero-length remainder.)  Lack of 
alteration is easier to define than change (because it is a state 
function, not a path function), and it is what all caching clients rely 
on for the validity of their caches.

There remains a gap in the information provided by this guarantee (and 
the current implementation): when no a-c-f region corresponds exactly to 
a preceding b-c-f call, clients are left to wonder whether more changes 
may yet occur.  At the least, we must publish all text before redisplay 
(to prevent the user from observing text not yet processed by a-c-f), 
but we can leave redisplay out of it by having each function which 
currently makes "unpaired" calls do one of several things when it exits:

1. Make an additional call to a-c-f that covers the whole region (which, 
in this interpretation, is not a violation because a-c-f is a promise 
not to modify in the future rather than a statement about modifications 
in the past).  This destroys the utility of the smaller a-c-f regions, 
of course.

2. Call some new hook to indicate that the remaining unlocked text has 
been republished in its original state.  (Note that it does not matter 
if the text was actually changed and then changed back, so long as all 
text properties and markers were restored and no other hooks were called.)

3. Make another call to b-c-f and a-c-f with, say, (point-max) 
(point-max).  We would then document that each call to b-c-f (for a 
buffer) indicates that any text not covered by a-c-f since the last 
b-c-f is republished unaltered.  This fits the current implementation 
and the intuitive idea that b-c-f is called before "each" change because 
it separates changes into epochs demarcated by b-c-f.

I therefore propose approach #3 as the minimal change to the current 
implementation that provides a behavioral guarantee worth documenting. 
Moreover, the demarcation of changes into epochs allows interested 
clients to work with the "paired" behavior by deferring a-c-f operations 
until the next b-c-f or precisely matching a-c-f.  (If all functions 
follow #3, then either the first a-c-f matches or the sequence will be 
terminated by a b-c-f.)

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or 
too sparse, it is because mass-energy conversion has occurred during 
shipping.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2) [Documentation fix still remaining]
  2016-09-01 21:25                                                                       ` Davis Herring
@ 2016-09-02  7:26                                                                         ` Eli Zaretskii
  0 siblings, 0 replies; 189+ messages in thread
From: Eli Zaretskii @ 2016-09-02  7:26 UTC (permalink / raw)
  To: Davis Herring; +Cc: dancol, monnier, emacs-devel

> Cc: emacs-devel@gnu.org
> From: Davis Herring <herring@lanl.gov>
> Date: Thu, 1 Sep 2016 15:25:01 -0600
> 
> > This is a naïve interpretation of what a "change" means and entails.
> > In reality, some changes are done with a single call to an insdel
> > function, while others need multiple calls that delete and insert text
> > piecemeal.  Thus the need to call the hooks before and after each
> > insdel call only sometimes.
> 
> Indeed, no one knows what we mean by "change".  To make progress, we 
> must introduce a formal definition for it

I envision that to be a very hard job, given the complexity of some
changes and the fact that at least some of them are not considered
"changes" for this purpose (see past discussions for the details).

Moreover, doing so was never the Emacs way.  Emacs always tries to do
things the naturally expected way, so that these issues don't arise.
If we need to go into such fine details and argue about formal
definitions of a "buffer change", that is a clear sign that something
is wrong and needs to be fixed, in a way that makes the "natural"
definition be implicitly correct, because the effect is as expected by
Lisp programmers.

Therefore, I think that spending any effort on making the manual text
more formally correct will be a wasted effort.  As long as the
implementation remains as it is now, the problem with its accurate
description in the manual will persist, and no small patches to the
code will resolve it completely.

> I therefore propose approach #3 as the minimal change to the current 
> implementation that provides a behavioral guarantee worth documenting. 

I don't think this issue can be attacked using only abstract
high-level considerations and resolved by solutions that are logically
complete, but may not be helpful in practice.

Instead, the use cases we want to support, both wrt the implementation
of complex changes we have in Emacs and wrt the users of these hooks,
should be collected and analyzed.  Then the best approach that
accommodates these needs (including perhaps any future needs we can
envision) should be designed and implemented.  My gut feeling is that
the correct model which will emerge from this will be very different
from what we have now.

Thanks.



^ permalink raw reply	[flat|nested] 189+ messages in thread

* Re: Unbalanced change hooks (part 2)
  2016-09-01 13:33             ` Stefan Monnier
@ 2016-09-02 11:34               ` Phillip Lord
  0 siblings, 0 replies; 189+ messages in thread
From: Phillip Lord @ 2016-09-02 11:34 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>> Okay, yes, I understand now, and yes, this should be conservative, in
>> the sense that it works for all changes, I guess. We are making the
>> assumption here that "start" is always consistent between b-c-f and
>> a-c-f,
>
> No, we don't make such an assumption either.  The assumption we make is
> that the region passed to a-c-f is within the region passed to b-c-f
> (i.e. is tighter).


Let me rephrase. Can I make the assumption that start is consistent? If
not I need to check to see whether they are inconsistent.

I'm testing the code out at the moment. My test cases work anyway, but
it will take more use in practice until I am confident.

Phil



^ permalink raw reply	[flat|nested] 189+ messages in thread

end of thread, other threads:[~2016-09-02 11:34 UTC | newest]

Thread overview: 189+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-31 12:16 Unbalanced change hooks (part 2) Alan Mackenzie
2016-07-31 13:58 ` Noam Postavsky
2016-07-31 15:21   ` Alan Mackenzie
2016-07-31 15:03 ` Eli Zaretskii
2016-07-31 17:28   ` Alan Mackenzie
2016-07-31 18:11     ` Eli Zaretskii
2016-07-31 18:52       ` Eli Zaretskii
2016-07-31 19:08         ` Eli Zaretskii
2016-07-31 19:20       ` Noam Postavsky
2016-07-31 21:26       ` Alan Mackenzie
2016-08-01 13:01         ` Stefan Monnier
2016-08-01 13:07         ` Eli Zaretskii
2016-08-01 16:53           ` Alan Mackenzie
2016-08-01 17:15             ` Alan Mackenzie
2016-08-01 19:39               ` Eli Zaretskii
2016-08-01 20:52                 ` Alan Mackenzie
2016-08-02 14:44                   ` Eli Zaretskii
2016-08-02 16:09                     ` Alan Mackenzie
2016-08-02 16:42                       ` Eli Zaretskii
2016-08-02 17:24                       ` Stefan Monnier
2016-08-07 14:49                         ` Alan Mackenzie
2016-08-07 15:09                           ` Stefan Monnier
2016-08-07 21:48                             ` Alan Mackenzie
2016-08-08  0:55                               ` Stefan Monnier
2016-08-02 14:46                   ` Stefan Monnier
2016-08-01 19:37             ` Eli Zaretskii
2016-08-02 14:39             ` Stefan Monnier
2016-07-31 18:55     ` Stefan Monnier
2016-07-31 19:26       ` Eli Zaretskii
2016-07-31 21:59         ` Stefan Monnier
2016-08-01 13:09           ` Eli Zaretskii
2016-08-01 14:36             ` Stefan Monnier
2016-08-01 14:48               ` Eli Zaretskii
2016-08-01 15:28                 ` Stefan Monnier
2016-07-31 19:33       ` Alan Mackenzie
2016-07-31 19:21     ` Eli Zaretskii
2016-08-09 15:01   ` Alan Mackenzie
2016-08-09 15:14     ` Eli Zaretskii
2016-08-19 14:51   ` Phillip Lord
2016-08-30  1:15     ` Stefan Monnier
2016-08-30 14:34       ` Phillip Lord
2016-08-30 15:11         ` Stefan Monnier
2016-08-31 11:00           ` Phillip Lord
2016-08-31 12:24             ` Stefan Monnier
2016-09-01  6:49               ` Phillip Lord
2016-09-01 13:36                 ` Stefan Monnier
2016-09-01  6:40           ` Phillip Lord
2016-09-01 13:33             ` Stefan Monnier
2016-09-02 11:34               ` Phillip Lord
2016-08-30 16:08         ` Eli Zaretskii
2016-08-01 16:38 ` Richard Stallman
2016-08-02 10:15   ` Alan Mackenzie
2016-08-02 10:37     ` Richard Copley
2016-08-02 16:11       ` Alan Mackenzie
2016-08-02 14:57     ` Eli Zaretskii
2016-08-02 16:55       ` Alan Mackenzie
2016-08-02 17:17         ` Eli Zaretskii
2016-08-02 18:30           ` Eli Zaretskii
2016-08-02 19:38             ` Alan Mackenzie
2016-08-03  2:36               ` Eli Zaretskii
2016-08-08 14:36             ` Alan Mackenzie
2016-08-08 15:42               ` Eli Zaretskii
2016-08-08 16:54                 ` Alan Mackenzie
2016-08-08 17:17                   ` Eli Zaretskii
2016-08-08 18:42                     ` Alan Mackenzie
2016-08-08 19:04                       ` Eli Zaretskii
2016-08-08 19:54                         ` Unbalanced change hooks (part 2) [PATCH] Alan Mackenzie
2016-08-09 15:08                           ` Eli Zaretskii
2016-08-09 16:38                             ` Unbalanced change hooks (part 2) [Documentation fix still remaining] Alan Mackenzie
2016-08-09 16:42                               ` Eli Zaretskii
2016-08-09 18:13                                 ` Eli Zaretskii
2016-08-09 18:35                                   ` Alan Mackenzie
2016-08-09 17:14                               ` Stefan Monnier
2016-08-09 18:19                                 ` Eli Zaretskii
2016-08-09 19:09                                   ` Stefan Monnier
2016-08-10 14:21                                     ` Eli Zaretskii
2016-08-10 14:56                                       ` Stefan Monnier
2016-08-10 15:16                                         ` Alan Mackenzie
2016-08-10 15:44                                           ` Stefan Monnier
2016-08-10 16:03                                         ` Eli Zaretskii
2016-08-10 16:11                                           ` Stefan Monnier
2016-08-18 14:26                                             ` Eli Zaretskii
2016-08-18 16:56                                               ` Stefan Monnier
2016-08-19  8:45                                               ` Alan Mackenzie
2016-08-19  9:12                                                 ` Eli Zaretskii
2016-08-19  9:21                                                   ` Stefan Monnier
2016-08-19  9:39                                                     ` Eli Zaretskii
2016-08-19  9:19                                                 ` Stefan Monnier
2016-08-10 16:18                                           ` Alan Mackenzie
2016-08-10 16:54                                             ` Eli Zaretskii
2016-08-10 17:49                                               ` Alan Mackenzie
2016-08-10 18:10                                                 ` Eli Zaretskii
2016-08-10 18:57                                               ` Alan Mackenzie
2016-08-10 19:08                                                 ` Eli Zaretskii
2016-08-10 19:50                                                 ` Stefan Monnier
2016-08-11 11:29                                                   ` Alan Mackenzie
2016-08-11 16:43                                                     ` Stefan Monnier
2016-08-28 11:23                                                       ` Daniel Colascione
2016-08-28 15:01                                                         ` Stefan Monnier
2016-08-28 22:16                                                           ` Daniel Colascione
2016-08-28 22:44                                                             ` Stefan Monnier
2016-08-28 23:11                                                               ` Daniel Colascione
2016-08-29  0:09                                                                 ` Stefan Monnier
2016-08-29  3:18                                                                   ` Daniel Colascione
2016-08-29 13:00                                                                     ` Stefan Monnier
2016-08-29 14:51                                                                       ` Eli Zaretskii
2016-08-29 15:50                                                                         ` Stefan Monnier
2016-08-29 16:22                                                                           ` Eli Zaretskii
2016-08-29 15:14                                                                       ` Daniel Colascione
2016-08-29 15:44                                                                         ` Stefan Monnier
2016-08-30 14:07                                                                           ` Phillip Lord
2016-08-30 15:51                                                                             ` Eli Zaretskii
2016-08-30 16:22                                                                               ` Daniel Colascione
2016-08-30 16:46                                                                                 ` Eli Zaretskii
2016-08-29 14:50                                                                     ` Eli Zaretskii
2016-08-29 15:30                                                                       ` Daniel Colascione
2016-08-29 16:20                                                                         ` Eli Zaretskii
2016-08-29 16:26                                                                           ` Daniel Colascione
2016-08-29 17:01                                                                             ` Eli Zaretskii
2016-08-29 17:48                                                                               ` Daniel Colascione
2016-08-29 18:04                                                                                 ` Eli Zaretskii
2016-08-29 18:16                                                                                   ` Eli Zaretskii
2016-08-30  2:27                                                                                     ` Daniel Colascione
2016-08-30  2:44                                                                                       ` Eli Zaretskii
2016-08-30  0:25                                                                                   ` Stefan Monnier
2016-08-30  2:26                                                                                     ` Daniel Colascione
2016-08-30  2:38                                                                                     ` Eli Zaretskii
2016-08-30  2:54                                                                                       ` Daniel Colascione
2016-08-30 14:20                                                                                         ` Phillip Lord
2016-08-30 15:08                                                                                         ` Eli Zaretskii
2016-08-30 12:56                                                                                       ` Stefan Monnier
2016-08-30 14:12                                                                       ` Phillip Lord
2016-08-30 16:06                                                                         ` Eli Zaretskii
2016-08-31 11:20                                                                           ` Phillip Lord
2016-08-31 14:57                                                                             ` Eli Zaretskii
2016-08-30 17:12                                                                       ` Alan Mackenzie
2016-08-30 17:27                                                                         ` Daniel Colascione
2016-08-30 17:42                                                                           ` Eli Zaretskii
2016-08-30 17:46                                                                             ` Daniel Colascione
2016-08-30 18:00                                                                               ` Eli Zaretskii
2016-08-30 18:04                                                                                 ` Daniel Colascione
2016-08-30 18:46                                                                                   ` Eli Zaretskii
2016-08-30 18:58                                                                                     ` Daniel Colascione
2016-08-30 19:17                                                                                       ` Eli Zaretskii
2016-08-30 21:46                                                                                     ` Stefan Monnier
2016-08-31  2:38                                                                                       ` Eli Zaretskii
2016-08-30 18:27                                                                                 ` Stefan Monnier
2016-09-01 13:46                                                                                   ` Eli Zaretskii
2016-08-30 18:01                                                                               ` Alan Mackenzie
2016-08-30 18:06                                                                                 ` Daniel Colascione
2016-08-30 18:17                                                                                   ` Daniel Colascione
2016-08-30 18:30                                                                                     ` Alan Mackenzie
2016-08-30 18:32                                                                                       ` Daniel Colascione
2016-08-30 18:47                                                                                         ` Alan Mackenzie
2016-08-30 18:55                                                                                           ` Daniel Colascione
2016-08-30 19:14                                                                                             ` Alan Mackenzie
2016-08-30 20:34                                                                                               ` Stefan Monnier
2016-08-30 20:53                                                                                                 ` Alan Mackenzie
2016-08-30 21:37                                                                                                   ` Stefan Monnier
2016-08-30 18:36                                                                                       ` Stefan Monnier
2016-08-30 18:22                                                                             ` Stefan Monnier
2016-08-30 18:00                                                                           ` Stefan Monnier
2016-08-30 17:27                                                                         ` Eli Zaretskii
2016-08-30 17:42                                                                           ` Alan Mackenzie
2016-08-30 17:53                                                                             ` Eli Zaretskii
2016-08-30 18:16                                                                               ` Alan Mackenzie
2016-08-30 18:51                                                                                 ` Eli Zaretskii
2016-08-30 19:00                                                                                   ` Alan Mackenzie
2016-08-30 18:14                                                                             ` Stefan Monnier
2016-09-01 21:25                                                                       ` Davis Herring
2016-09-02  7:26                                                                         ` Eli Zaretskii
2016-08-28 22:36                                                         ` Stefan Monnier
2016-08-30 13:30                                                         ` Phillip Lord
2016-08-30 13:39                                                           ` Stefan Monnier
2016-08-31 11:04                                                             ` Phillip Lord
2016-08-30 15:47                                                           ` Eli Zaretskii
2016-08-30 16:01                                                             ` Stefan Monnier
2016-08-30 16:58                                                               ` Eli Zaretskii
2016-08-30 17:57                                                                 ` Stefan Monnier
2016-08-31 11:17                                                                   ` Phillip Lord
2016-08-31 11:12                                                                 ` Phillip Lord
2016-08-30 16:23                                                             ` Daniel Colascione
2016-08-30 16:53                                                               ` Eli Zaretskii
2016-08-02 19:00           ` Unbalanced change hooks (part 2) Alan Mackenzie
2016-08-02 19:25             ` Eli Zaretskii
2016-08-07 21:16               ` Alan Mackenzie
2016-08-08 15:38                 ` Eli Zaretskii
2016-08-08 19:56                 ` Stefan Monnier
2016-08-08 20:16                   ` Alan Mackenzie

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).