Subject: bug#21391: 24.5; `thing-at-point' should return a string

From: Drew Adams <[email-masked]>
Date: Mon, 7 Nov 2016 08:10:34 -0800 (PST)

> > > A proper fix is to convert the result returned by
> > > (funcall (get thing 'thing-at-point)) to a string.
> > > For that, you can use (format "%s" thing).
> >
> > It's natural if `thing-at-point' returns the thing as a string.
> > When the user don't want a string then s?he can use the specific
> > functions, like `number-at-point' or `list-at-point'.
> 
> Isn't that completely backward-incompatible?  If so, I don't think
> we can do that.
> 
> I don't really see what is "improper" with the other suggestions to
> fix this bug, which simply avoid signaling an error if the "thing at
> point" happens to be something other than a string?

`thing-at-point' has always allowed, and rightfully so, its default
behavior to be replaced by putting a function on the THING symbol as
property `thing-at-point'.  That function is invoked, and what the
return value was returned by `thing-at-point'.

The two branches of the `if' in `thing-at-point' were thus not
symmetrical (and intentionally so, so that it could return actual
things, not just strings naming things).  One branch could return
anything - a THING at point; the other branch returned a string
naming a thing at point.

This meant that `thing-at-point' could return a list, symbol, etc.
- things that are not strings.

What is new (since Emacs 24.4) is that someone added this at the end
of the definition of `thing-at-point', and made it pertain to _both_
branches of the `if'.  In addition, they named the result of the `if'
by the variable `text'.

(when (and text no-properties)
  (set-text-properties 0 (length text) nil text))

They apparently paid no attention to the important `thing-at-point'
behavior provided by the first `if' clause, and instead just assumed
that the `if' always returned a string.

IIUC, Emacs Dev (not I), has insisted that `thing-at-point' itself
should always return a string, as opposed to what `form-at-point'
(and functions defined using it) returns, which can be a THING (not
just a string naming a thing).  For one thing, this allows code
calling `thing-at-point' to count on the result being a string (if
a thing is found) or nil (if not).

I see three possibly reasonable fixes for the bug introduced in
Emacs 24.4:

1. Make `thing-at-point' always return a thing, as (IIUC) wished
   by Emacs Dev.  Have it convert the result of the first `if'
   clause to a string.  Anyone needing a real (non-string) thing
   can use `form-at-point' to get what they want.

2. Make `thing-at-point', as before, return just what the firat
   `if' clause returns, if that clause is taken.  IOW, move the
   removal of text properties (from non-nil NO-PROPERTIES) into
   the second `if' clause.  Among other things (sic), this allows
   the first `if' clause to return a propertized string.

3. Make `thing-at-point', as before, return just what the firat
   `if' clause returns, if that clause is taken, except that if
   either clause returns a string then strip that string of text
   properties (if NO-PROPERTIES is non-nil).

My understanding is that Emacs Dev has preferred that
`thing-at-point' return a string, and that users should use
`form-at-point' if they want something else.  (I've adapted my
own code to that preference.)

If so, then #1 is probably the option of choice: Convert anything
returned by (funcall (get thing 'thing-at-point)) to a string.

Personally, I do not see why Emacs added arg NO-PROPERTIES, as
anyone could always remove properties on a string result from
`thing-at-point'.  Dunno who added this arg, or why, but I
don't see that it provides any advantage.

(Perhaps the one advantage it has inadvertently provided is to
raise the question again of whether `thing-at-point' should
always return a string.)