Subject: bug#41761: [PATCH] bug#41761: 28.0.50; M-x count-words counts words only up to a field boundary

From: Daniel Koning <[email-masked]>
Date: Sun, 16 Aug 2020 14:04:14 -0500

Eli Zaretskii <[email-masked]> writes:

>> I do think the prior behavior differs somewhat from the way you phrased
>> it. I would write it as:
>>
>>     Originally, when 'inhibit-field-text-motion' was nil, 'count-words'
>>     stopped counting words at the end of the field containing START.
>>
>> (It didn't ignore text inside fields, but rather text that was not
>> inside one specific field.)
>
> I'm not sure I understand the "end of field containing START" part.
> Supposed the region includes several fields, what would the previous
> code do?

It would only count the words between START and the next field boundary,
no matter how many fields came after that. (For START, substitute "the
beginning of the region" or "the beginning of the buffer" if it was
called interactively.)

Try reinstalling the old function definition and evaluating:

ELISP> (with-temp-buffer
         (dotimes (i 9) (insert (propertize "4 words 22 characters " 'field i)))
         (insert "\n4 words 22 characters")
         (call-interactively #'count-words)) ; operates on whole buffer

=> "Buffer has 2 lines, 4 words, and 220 characters."

That result arises because of how `count-words' generates its return
value: it moves point to the beginning of the buffer (after narrowing
the buffer to START and END if they were supplied), then repeatedly
calls `forward-word-strictly' until that function returns nil,
incrementing the running total each time. Before, if it ran into a field
boundary, it would stop short, because `forward-word-strictly' doesn't
jump field boundaries by default.

I think the value of that form demonstrates why the old behavior was
wrong. There does not exist any part of the temp buffer that "has 2
lines, 4 words, and 220 characters." It gives inconsistent results
because the line count and character count use techniques which aren't
affected by fields.

Daniel