Subject: bug#21391: 24.5; `thing-at-point' returns error when called with arguments 'number t)

From: Drew Adams <[email-masked]>
Date: Fri, 4 Nov 2016 13:03:40 -0700 (PDT)

Sorry, but I confused things further, I'm afraid.

`thing-at-point' should always return a string.
`list-at-point', `form-at-point', etc. are a different
story - they can return anything.

The problem with the code of `thing-at-point' is not where
it has been identified so far.  The problem is that if
THING has property `thing-at-point', and if that function
returns something that is not a string, then
`set-text-properties' raises an error.

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).

FWIW, this is the code that I use (prefix `tap-' is for
the package).  Note that the doc string's first line says
that what is returned is a string.

(defun tap-thing-at-point (thing &optional no-properties syntax-table)
  "Return the THING at point as a string.
If no THING is present at point then return nil.

THING is an Emacs Lisp symbol that specifies a type of syntactic
entity.  THING examples include `symbol', `list', `sexp', `defun',
`filename', `url', `email', `word', `sentence', `whitespace', `line',
`number', and `page'.  See the commentary of library `thingatpt.el'
for how to define a symbol as a valid THING.

If THING has property `thing-at-point' then the property value should
be a function.  The function is called with no arguments.  If the
return value of that function is a string or nil then that value is
returned by this function also.  Otherwise, that value is converted to
a string and returned.

Optional arg NO-PROPERTIES means that if a string is to be returned
then it is first stripped of any text properties.

Optional arg SYNTAX-TABLE is a syntax table to use."
  (let* ((thing-fn  (or (get thing 'tap-thing-at-point)  
                        (get thing 'thing-at-point)))
         (text
          (if thing-fn
              (let* ((opoint  (point))
                     (thg     (prog1 (funcall thing-fn)
                                (constrain-to-field nil opoint))))
                (if (stringp thg)
                    thg
                  (and thg  (format "%s" thg))))
            (let ((bounds  (tap-bounds-of-thing-at-point
                             thing syntax-table)))
              (and bounds  (buffer-substring (car bounds)
                                             (cdr bounds)))))))
    (when (and text  no-properties)
      (set-text-properties 0 (length text) nil text))
    text))