Subject: bug#76313: New function `replace-region`

From: Stefan Monnier <[email-masked]>
Date: Sat, 29 Mar 2025 18:20:15 -0400

>> From: Stefan Monnier <[email-masked]>
>> Cc: Stefan Kangas <[email-masked]>,  [email-masked],
>>   [email-masked],  [email-masked]
>> Date: Fri, 28 Mar 2025 11:38:19 -0400
>> 
>> Any chance we could consider a  breaking change and force a non-nil value of
>> one of MAX-SECS or MAX-COSTS before the function is allowed to use the
>> costly algorithm?
>
> I'd prefer a completely backward-compatible change of passing a
> special value of MAX-SECS to indicate that the potentially costly
> algorithm is to be bypassed.

We already have that: pass a 0 for MAX-SECS.

But I've changed my mind: I don't think we should unify
`replace-region-contents` and my proposed `replace-region`.

When I sent the patches there were still some tests failing, and
I assumed these were just the result of idiotic errors on my part which
I'd fix the next day (it was late).

While that was partly true, some of the problems were a lot more
delicate: while `replace-region` is "easy" to use to do what I would
describe as "edits", `replace-region-contents` is a good bit more
delicate because its effect on point is less predictable.

When point is "in the middle" of the modified text, all is fine callers
usually don't expect any specific position for point after wards, in
that case.  But if point is at the beginning (resp. at the end) of the text
being replaced, most callers expect it to still be at the beginning
(resp. the end) of the new text afterwards.

This does hold when point is at the beginning of the text but *not* when
it's at the end.  So in a typical loop scanning a buffer with
`re-search-forward` and then calling `replace-region-contents`, it's
easy to get bitten by it when occasionally we'll end up finding a match
in the text we just inserted because the "careful" version of
`replace-region-contents` moved point back somewhat.

IOW, if you have code that uses

    (replace-region-contents BEG END SOURCE 0)

and you change it to:

    (replace-region-contents BEG END SOURCE 0.1)

thinking "oh, I can afford to spend a bit more time here, let's
enable the fancy diff algorithm", you may end up breaking your code.

        Stefan