Subject: 24.0.50; `number-at-point' returns char value for `?' constructs - 1) doc, 2) new fns

From: "Drew Adams" <[email-masked]>
Date: Sat, 7 May 2011 08:30:22 -0700

`number-at-point' is defined like this:

(defun number-at-point ()
  "Return the number at point, or nil if none is found."
  (form-at-point 'sexp 'numberp))

That uses `read-from-string' for the sexp at point, and testing whether the
result is `numberp'.

That's fine, I guess, but it means that with buffer text such as ?A or ?\A-\^@
you get a non-nil result: the character value (wholenump) for ?A, which is 65,
and 4194304, respectively.  If you are depending on code to find _numerals_ in
text and return their numeric values then this is not what you want.  In that
case, you want a function that returns nil when point is not on a numeral.

The current behavior could admittedly be useful sometimes, but:

1. This should be mentioned in the doc string, as it's hardly what an uninformed
user would expect, especially a newbie who doesn't yet know Emacs's char
representation (`?.') and the fact that, for Emacs, chars are numbers.  This
behavior is not obvious, given the current doc and function name.

2. It might not be what the user or calling code really _wants_ in many (most?)
cases.

It's no doubt too late to change the name (e.g. to something like
`number-or-char-at-point').  Some existing code probably depends on the current
behavior.

But it's not too late to add functions that do what many people might expect:
return the number represented by the numeral at point, or nil if there is no
numeral at point.

Here are two functions that could be added.  Whether you add them or not, please
do mention the full behavior (with the gotcha) in the `number-at-point' doc
string.

(defun number-at-point-decimal ()
  "Return the number represented by the decimal numeral at point.
Return nil if none is found."
  (let ((strg  (thing-at-point 'sexp)))
    (and (stringp strg)        
         (if (fboundp 'string-match-p)
             (string-match-p "\\`[0-9]+\\'" strg)
           (string-match "\\`[0-9]+\\'" strg))
         (string-to-number strg))))

(defun number-at-point-hex ()
  "Return the number represented by the hex numeral at point.
Return nil if none is found."
  (let ((strg  (thing-at-point 'sexp)))
    (and (stringp strg)
         (if (fboundp 'string-match-p)
             (string-match-p "\\`[0-9a-fA-F]+\\'" strg)
           (string-match "\\`[0-9a-fA-F]+\\'" strg))
         (string-to-number strg 16))))

In GNU Emacs 24.0.50.1 (i386-mingw-nt5.1.2600)
 of 2011-04-25 on 3249CTO
Windowing system distributor `Microsoft Corp.', version 5.1.2600
configured using `configure --with-gcc (4.5) --no-opt --cflags
-Ic:/imagesupport/include'