Subject: bug#9300: 24.0.50; `bounds-of-thing-at-point' does not return nil when just after THING

From: Drew Adams <[email-masked]>
Date: Tue, 23 Feb 2016 17:31:02 -0800 (PST)

> > Yes, it should return nil, as there is NO symbol at point.
> 
> If we ask the users, I'm guessing we'll get mixed answers on that, at
> least as a result of this long-standing thing-at-point behavior.

You might get opinions, but the fact is that there is no thing at
point in that case.

"At point" can only mean, since point is between characters, either
before point or after point.  It cannot mean both.  Not and keep
a possibility of recursive/iterative use.  Moving forward over a
thing puts point after the thing.  It does not keep point on/at
the thing.

The design must pick one or the other meaning of "at": a character
that belongs to the THING at point is either after or before point.
It cannot reasonably be both.

IMO, and all of the code confirms this (apart from this bug): "at"
in "thing at point" means after point, not before point.

> > It is your expectation that is wrong.  There are plenty of uses
> > of thing-at-point that go far beyond just looking for a default
> > value of a name near point or trying to complete a name before
> > (not at) point.
> 
> What I'm saying is, "fixing" it will most likely break code in the wild.
> Not just mine.

The fix to your code and theirs is trivial.

Bit if you must, rename the current, bugged implementation of
`bounds-of-thing-at-point' to `bounds-of-thing-at-or-after-point'.
Tell such folks to use that.  Likewise, add `thing-at-or-after-point',
if necessary, for any code that current depends on the broken
`thing-at-point'.

If you must, do that plus deprecate the (perfectly good, but not
for this broken code) name `bounds-of-thing-at-point', so any such
3rd-party code makes the change.

And add a function `bounds-of-thing-at-point-strict' that does
what `bounds-of-thing-at-point' should do (= the bug fix).  Change
the Emacs code that uses the broken `bounds-of-thing-at-point' to
use `bounds-of-thing-at-point-strict'.

IOW, wean any code from the broken implementation and use the
fixed implementation.

This is if you are convinced that there are zillions of uses of
the bugged `bounds-of-thing-at-point' that depend on the bugged
behavior.  I'm not convinced of that.

I'd say bite the bullet: fix the bug properly, and when anyone
complains tell them to use `bounds-of-thing-at-or-after-point'
if they really want the bugged behavior.  Better: tell them
to use the fixed `bounds-of-thing-at-point' after backing up
so point is actually on the THING instead of after it.

> > Those other uses include the need to test whether or not there
> > IS a given THING at point.  The design itself depends on this
> > difference: Is there a THING at point or not?
> 
> They can call (bounds-of-thing-at-point 'foo), and then compare
> the cdr with the value of point.

You are missing the point.  I won't repeat myself.  See what
I wrote about use cases.  See the code I referenced, if needed.

> >>> This is the design of the thingatpt code, and the reason why
> >>> `<=' instead of `<' is a bug:
> >>>
> >>>    the function that is (get THING 'end-op) moves PAST the THING,
> >>>    so that point is not on the THING.  This is true generally, no
> >>>    matter the type of THING.
> >>
> >> That's not a quote from thingatpt.el.
> >
> > It is nevertheless the design (intention), clear from the code.
> 
> I'm not so clear on that.

That much is clear.

> The following comment tells me the opposite
> (the position where a substring ends is normally the one _after_ its
> last character):
> 
>      ;; Try a second time, moving backward first and then forward,
>      ;; so that we can find a thing that ends at ORIG.

ORIG is the original position.  A thing that ends at that position
is at point.  A thing that ends before that position is not a thing
at point.

Look at `goto-char' or any other char-counting functions.  If you
move point "to" character 2, point = 2.  The char "at" point is the
char after point - point is before the char that has the same number
as point.  When point = 2 the cursor position (aka point) is between
chars 1 and 2, and we say point is "at" (or "looking at") char 2.

> If we didn't need to be able to find a thing that ends just before
> point,

Before is not at (= after).  Ends at ORIG does not mean ends before
ORIG.

> I don't think the implementation would need the "Try a second
> time" branch at all: when point if before the last character of a
> symbol, (forward-symbol) still works.

Believe me, I've walked through that particular code a hundred
times, in the debugger and without.  The code you are referring
to is needed, and it is not about finding a thing that ends before
point.

But I think you either try to see or you don't.  I cannot make
you see.